aboutsummaryrefslogtreecommitdiff
path: root/gnu/usr.bin/gdb
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/gdb')
-rw-r--r--gnu/usr.bin/gdb/COPYING354
-rw-r--r--gnu/usr.bin/gdb/COPYING.LIB481
-rw-r--r--gnu/usr.bin/gdb/ChangeLog4887
-rw-r--r--gnu/usr.bin/gdb/Gdbinit15
-rw-r--r--gnu/usr.bin/gdb/Makefile39
-rw-r--r--gnu/usr.bin/gdb/Makefile.dist371
-rw-r--r--gnu/usr.bin/gdb/Projects114
-rw-r--r--gnu/usr.bin/gdb/README.FreeBSD15
-rw-r--r--gnu/usr.bin/gdb/README.gnu142
-rw-r--r--gnu/usr.bin/gdb/VERSION1
-rw-r--r--gnu/usr.bin/gdb/XGdbinit.samp15
-rw-r--r--gnu/usr.bin/gdb/Xgdb.ad8
-rw-r--r--gnu/usr.bin/gdb/bfd/COPYING339
-rw-r--r--gnu/usr.bin/gdb/bfd/Makefile17
-rw-r--r--gnu/usr.bin/gdb/bfd/README.FreeBSD7
-rw-r--r--gnu/usr.bin/gdb/bfd/VERSION1
-rw-r--r--gnu/usr.bin/gdb/bfd/aout-target.h429
-rw-r--r--gnu/usr.bin/gdb/bfd/aout32.c23
-rw-r--r--gnu/usr.bin/gdb/bfd/aoutx.h2568
-rw-r--r--gnu/usr.bin/gdb/bfd/archive.c1770
-rw-r--r--gnu/usr.bin/gdb/bfd/archures.c731
-rw-r--r--gnu/usr.bin/gdb/bfd/bfd.c733
-rw-r--r--gnu/usr.bin/gdb/bfd/bfd.h1803
-rw-r--r--gnu/usr.bin/gdb/bfd/cache.c311
-rw-r--r--gnu/usr.bin/gdb/bfd/coffgen.c1519
-rw-r--r--gnu/usr.bin/gdb/bfd/core.c106
-rw-r--r--gnu/usr.bin/gdb/bfd/cpu-i386.c43
-rw-r--r--gnu/usr.bin/gdb/bfd/ctor.c148
-rw-r--r--gnu/usr.bin/gdb/bfd/ecoff.c3994
-rw-r--r--gnu/usr.bin/gdb/bfd/elf.c248
-rw-r--r--gnu/usr.bin/gdb/bfd/format.c258
-rw-r--r--gnu/usr.bin/gdb/bfd/freebsd386.c110
-rw-r--r--gnu/usr.bin/gdb/bfd/init.c78
-rw-r--r--gnu/usr.bin/gdb/bfd/libaout.h393
-rw-r--r--gnu/usr.bin/gdb/bfd/libbfd.c850
-rw-r--r--gnu/usr.bin/gdb/bfd/libbfd.h273
-rw-r--r--gnu/usr.bin/gdb/bfd/libcoff.h352
-rw-r--r--gnu/usr.bin/gdb/bfd/libecoff.h265
-rw-r--r--gnu/usr.bin/gdb/bfd/libelf.h249
-rw-r--r--gnu/usr.bin/gdb/bfd/opncls.c534
-rw-r--r--gnu/usr.bin/gdb/bfd/reloc.c1225
-rw-r--r--gnu/usr.bin/gdb/bfd/seclet.c185
-rw-r--r--gnu/usr.bin/gdb/bfd/seclet.h55
-rw-r--r--gnu/usr.bin/gdb/bfd/section.c899
-rw-r--r--gnu/usr.bin/gdb/bfd/srec.c1001
-rw-r--r--gnu/usr.bin/gdb/bfd/stab-syms.c59
-rw-r--r--gnu/usr.bin/gdb/bfd/syms.c527
-rw-r--r--gnu/usr.bin/gdb/bfd/sysdep.h47
-rw-r--r--gnu/usr.bin/gdb/bfd/targets.c635
-rw-r--r--gnu/usr.bin/gdb/bfd/trad-core.c384
-rw-r--r--gnu/usr.bin/gdb/blockframe.c622
-rw-r--r--gnu/usr.bin/gdb/breakpoint.c1383
-rw-r--r--gnu/usr.bin/gdb/command.h77
-rw-r--r--gnu/usr.bin/gdb/config/Makefile.i3866
-rw-r--r--gnu/usr.bin/gdb/config/default-dep.c585
-rw-r--r--gnu/usr.bin/gdb/config/i386-dep.c1275
-rw-r--r--gnu/usr.bin/gdb/config/i386bsd-dep.c1886
-rw-r--r--gnu/usr.bin/gdb/config/m-i386-sv32.h28
-rw-r--r--gnu/usr.bin/gdb/config/m-i386bsd.h375
-rw-r--r--gnu/usr.bin/gdb/config/m-i386g-sv32.h28
-rw-r--r--gnu/usr.bin/gdb/config/m-i386gas.h37
-rw-r--r--gnu/usr.bin/gdb/copying.c215
-rw-r--r--gnu/usr.bin/gdb/core.c581
-rw-r--r--gnu/usr.bin/gdb/cplus-dem.c996
-rw-r--r--gnu/usr.bin/gdb/dbxread.c5727
-rw-r--r--gnu/usr.bin/gdb/defs.h122
-rw-r--r--gnu/usr.bin/gdb/doc/ChangeLog783
-rw-r--r--gnu/usr.bin/gdb/doc/Makefile340
-rw-r--r--gnu/usr.bin/gdb/doc/Makefile.in327
-rw-r--r--gnu/usr.bin/gdb/doc/a4rc.sed11
-rw-r--r--gnu/usr.bin/gdb/doc/all-cfg.texi117
-rwxr-xr-xgnu/usr.bin/gdb/doc/config.status5
-rw-r--r--gnu/usr.bin/gdb/doc/configure.in7
-rw-r--r--gnu/usr.bin/gdb/doc/gdb-cfg.texi117
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info213
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info-11304
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info-21165
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info-31264
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info-41349
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info-51215
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info-61220
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info-71233
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.info-8657
-rw-r--r--gnu/usr.bin/gdb/doc/gdb.texinfo8591
-rw-r--r--gnu/usr.bin/gdb/doc/gdbint.texinfo2658
-rw-r--r--gnu/usr.bin/gdb/doc/h8-cfg.texi47
-rw-r--r--gnu/usr.bin/gdb/doc/libgdb.texinfo1471
-rw-r--r--gnu/usr.bin/gdb/doc/lpsrc.sed13
-rw-r--r--gnu/usr.bin/gdb/doc/psrc.sed13
-rw-r--r--gnu/usr.bin/gdb/doc/refcard.ps798
-rw-r--r--gnu/usr.bin/gdb/doc/refcard.tex646
-rw-r--r--gnu/usr.bin/gdb/doc/remote.texi1294
-rw-r--r--gnu/usr.bin/gdb/doc/stabs.texinfo3795
-rw-r--r--gnu/usr.bin/gdb/environ.c185
-rw-r--r--gnu/usr.bin/gdb/environ.h39
-rw-r--r--gnu/usr.bin/gdb/expprint.c324
-rw-r--r--gnu/usr.bin/gdb/expread.y1782
-rw-r--r--gnu/usr.bin/gdb/findvar.c579
-rw-r--r--gnu/usr.bin/gdb/frame.h115
-rw-r--r--gnu/usr.bin/gdb/gdb.13
-rw-r--r--gnu/usr.bin/gdb/gdb/COPYING339
-rw-r--r--gnu/usr.bin/gdb/gdb/Makefile72
-rw-r--r--gnu/usr.bin/gdb/gdb/ansidecl.h139
-rw-r--r--gnu/usr.bin/gdb/gdb/aout/aout64.h431
-rw-r--r--gnu/usr.bin/gdb/gdb/aout/ar.h32
-rw-r--r--gnu/usr.bin/gdb/gdb/aout/ranlib.h62
-rw-r--r--gnu/usr.bin/gdb/gdb/aout/stab.def264
-rw-r--r--gnu/usr.bin/gdb/gdb/aout/stab_gnu.h36
-rw-r--r--gnu/usr.bin/gdb/gdb/blockframe.c821
-rw-r--r--gnu/usr.bin/gdb/gdb/breakpoint.c3301
-rw-r--r--gnu/usr.bin/gdb/gdb/breakpoint.h372
-rw-r--r--gnu/usr.bin/gdb/gdb/buildsym.c950
-rw-r--r--gnu/usr.bin/gdb/gdb/buildsym.h259
-rw-r--r--gnu/usr.bin/gdb/gdb/c-exp.y1601
-rw-r--r--gnu/usr.bin/gdb/gdb/c-lang.c447
-rw-r--r--gnu/usr.bin/gdb/gdb/c-lang.h31
-rw-r--r--gnu/usr.bin/gdb/gdb/c-typeprint.c797
-rw-r--r--gnu/usr.bin/gdb/gdb/c-valprint.c416
-rw-r--r--gnu/usr.bin/gdb/gdb/call-cmds.h28
-rw-r--r--gnu/usr.bin/gdb/gdb/ch-exp.y1997
-rw-r--r--gnu/usr.bin/gdb/gdb/ch-lang.c341
-rw-r--r--gnu/usr.bin/gdb/gdb/ch-lang.h31
-rw-r--r--gnu/usr.bin/gdb/gdb/ch-typeprint.c225
-rw-r--r--gnu/usr.bin/gdb/gdb/ch-valprint.c332
-rw-r--r--gnu/usr.bin/gdb/gdb/coff/ecoff.h262
-rw-r--r--gnu/usr.bin/gdb/gdb/coff/internal.h538
-rw-r--r--gnu/usr.bin/gdb/gdb/coff/sym.h477
-rw-r--r--gnu/usr.bin/gdb/gdb/coff/symconst.h175
-rw-r--r--gnu/usr.bin/gdb/gdb/coffread.c2071
-rw-r--r--gnu/usr.bin/gdb/gdb/command.c (renamed from gnu/usr.bin/gdb/command.c)744
-rw-r--r--gnu/usr.bin/gdb/gdb/command.h241
-rw-r--r--gnu/usr.bin/gdb/gdb/complaints.c158
-rw-r--r--gnu/usr.bin/gdb/gdb/complaints.h46
-rw-r--r--gnu/usr.bin/gdb/gdb/copying.c327
-rw-r--r--gnu/usr.bin/gdb/gdb/core.c291
-rw-r--r--gnu/usr.bin/gdb/gdb/coredep.c118
-rw-r--r--gnu/usr.bin/gdb/gdb/corelow.c328
-rw-r--r--gnu/usr.bin/gdb/gdb/cp-valprint.c484
-rw-r--r--gnu/usr.bin/gdb/gdb/dbxread.c2234
-rw-r--r--gnu/usr.bin/gdb/gdb/dcache.c236
-rw-r--r--gnu/usr.bin/gdb/gdb/dcache.h83
-rw-r--r--gnu/usr.bin/gdb/gdb/defs.h901
-rw-r--r--gnu/usr.bin/gdb/gdb/demangle.c190
-rw-r--r--gnu/usr.bin/gdb/gdb/demangle.h77
-rw-r--r--gnu/usr.bin/gdb/gdb/dis-asm.h176
-rw-r--r--gnu/usr.bin/gdb/gdb/dis-buf.c69
-rw-r--r--gnu/usr.bin/gdb/gdb/dwarfread.c3866
-rw-r--r--gnu/usr.bin/gdb/gdb/elf/common.h216
-rw-r--r--gnu/usr.bin/gdb/gdb/elf/dwarf.h314
-rw-r--r--gnu/usr.bin/gdb/gdb/elf/external.h190
-rw-r--r--gnu/usr.bin/gdb/gdb/elf/internal.h195
-rw-r--r--gnu/usr.bin/gdb/gdb/elfread.c729
-rw-r--r--gnu/usr.bin/gdb/gdb/environ.c198
-rw-r--r--gnu/usr.bin/gdb/gdb/environ.h58
-rw-r--r--gnu/usr.bin/gdb/gdb/eval.c (renamed from gnu/usr.bin/gdb/eval.c)744
-rw-r--r--gnu/usr.bin/gdb/gdb/exec.c489
-rw-r--r--gnu/usr.bin/gdb/gdb/expprint.c623
-rw-r--r--gnu/usr.bin/gdb/gdb/expression.h (renamed from gnu/usr.bin/gdb/expression.h)164
-rw-r--r--gnu/usr.bin/gdb/gdb/findvar.c971
-rw-r--r--gnu/usr.bin/gdb/gdb/fopen-same.h27
-rw-r--r--gnu/usr.bin/gdb/gdb/fork-child.c310
-rw-r--r--gnu/usr.bin/gdb/gdb/frame.h238
-rw-r--r--gnu/usr.bin/gdb/gdb/freebsd-nat.c323
-rw-r--r--gnu/usr.bin/gdb/gdb/freebsd-solib.c1469
-rw-r--r--gnu/usr.bin/gdb/gdb/gdb-stabs.h76
-rw-r--r--gnu/usr.bin/gdb/gdb/gdb.1371
-rw-r--r--gnu/usr.bin/gdb/gdb/gdbcmd.h101
-rw-r--r--gnu/usr.bin/gdb/gdb/gdbcore.h129
-rw-r--r--gnu/usr.bin/gdb/gdb/gdbtypes.c1440
-rw-r--r--gnu/usr.bin/gdb/gdb/gdbtypes.h704
-rw-r--r--gnu/usr.bin/gdb/gdb/getopt.h129
-rw-r--r--gnu/usr.bin/gdb/gdb/i386-dis.c (renamed from gnu/usr.bin/gdb/config/i386-pinsn.c)302
-rw-r--r--gnu/usr.bin/gdb/gdb/i386-pinsn.c37
-rw-r--r--gnu/usr.bin/gdb/gdb/i386-tdep.c595
-rw-r--r--gnu/usr.bin/gdb/gdb/infcmd.c1423
-rw-r--r--gnu/usr.bin/gdb/gdb/inferior.h401
-rw-r--r--gnu/usr.bin/gdb/gdb/inflow.c662
-rw-r--r--gnu/usr.bin/gdb/gdb/infptrace.c436
-rw-r--r--gnu/usr.bin/gdb/gdb/infrun.c1848
-rw-r--r--gnu/usr.bin/gdb/gdb/inftarg.c310
-rw-r--r--gnu/usr.bin/gdb/gdb/init.c47
-rw-r--r--gnu/usr.bin/gdb/gdb/language.c1332
-rw-r--r--gnu/usr.bin/gdb/gdb/language.h413
-rw-r--r--gnu/usr.bin/gdb/gdb/m2-exp.y1169
-rw-r--r--gnu/usr.bin/gdb/gdb/m2-lang.c457
-rw-r--r--gnu/usr.bin/gdb/gdb/m2-lang.h31
-rw-r--r--gnu/usr.bin/gdb/gdb/m2-typeprint.c49
-rw-r--r--gnu/usr.bin/gdb/gdb/m2-valprint.c45
-rw-r--r--gnu/usr.bin/gdb/gdb/main.c2799
-rw-r--r--gnu/usr.bin/gdb/gdb/maint.c305
-rw-r--r--gnu/usr.bin/gdb/gdb/mem-break.c104
-rw-r--r--gnu/usr.bin/gdb/gdb/minsyms.c597
-rw-r--r--gnu/usr.bin/gdb/gdb/mipsread.c3653
-rw-r--r--gnu/usr.bin/gdb/gdb/nlmread.c300
-rw-r--r--gnu/usr.bin/gdb/gdb/nm.h44
-rw-r--r--gnu/usr.bin/gdb/gdb/objfiles.c773
-rw-r--r--gnu/usr.bin/gdb/gdb/objfiles.h437
-rw-r--r--gnu/usr.bin/gdb/gdb/obstack.h (renamed from gnu/usr.bin/gdb/obstack.h)226
-rw-r--r--gnu/usr.bin/gdb/gdb/parse.c827
-rw-r--r--gnu/usr.bin/gdb/gdb/parser-defs.h188
-rw-r--r--gnu/usr.bin/gdb/gdb/partial-stab.h618
-rw-r--r--gnu/usr.bin/gdb/gdb/printcmd.c (renamed from gnu/usr.bin/gdb/printcmd.c)1459
-rw-r--r--gnu/usr.bin/gdb/gdb/putenv.c111
-rw-r--r--gnu/usr.bin/gdb/gdb/regex.c (renamed from gnu/usr.bin/gdb/regex.c)61
-rw-r--r--gnu/usr.bin/gdb/gdb/regex.h (renamed from gnu/usr.bin/gdb/regex.h)32
-rw-r--r--gnu/usr.bin/gdb/gdb/remote-utils.c645
-rw-r--r--gnu/usr.bin/gdb/gdb/remote-utils.h149
-rw-r--r--gnu/usr.bin/gdb/gdb/remote.c1272
-rw-r--r--gnu/usr.bin/gdb/gdb/ser-unix.c633
-rw-r--r--gnu/usr.bin/gdb/gdb/serial.c261
-rw-r--r--gnu/usr.bin/gdb/gdb/serial.h153
-rw-r--r--gnu/usr.bin/gdb/gdb/signals.h27
-rw-r--r--gnu/usr.bin/gdb/gdb/solib.h56
-rw-r--r--gnu/usr.bin/gdb/gdb/source.c1398
-rw-r--r--gnu/usr.bin/gdb/gdb/stabsread.c3770
-rw-r--r--gnu/usr.bin/gdb/gdb/stabsread.h194
-rw-r--r--gnu/usr.bin/gdb/gdb/stack.c1379
-rw-r--r--gnu/usr.bin/gdb/gdb/symfile.c1489
-rw-r--r--gnu/usr.bin/gdb/gdb/symfile.h228
-rw-r--r--gnu/usr.bin/gdb/gdb/symmisc.c857
-rw-r--r--gnu/usr.bin/gdb/gdb/symtab.c3035
-rw-r--r--gnu/usr.bin/gdb/gdb/symtab.h1124
-rw-r--r--gnu/usr.bin/gdb/gdb/target.c789
-rw-r--r--gnu/usr.bin/gdb/gdb/target.h465
-rw-r--r--gnu/usr.bin/gdb/gdb/terminal.h62
-rw-r--r--gnu/usr.bin/gdb/gdb/thread.c248
-rw-r--r--gnu/usr.bin/gdb/gdb/thread.h36
-rw-r--r--gnu/usr.bin/gdb/gdb/tm-i386v.h (renamed from gnu/usr.bin/gdb/config/m-i386.h)213
-rw-r--r--gnu/usr.bin/gdb/gdb/tm.h76
-rw-r--r--gnu/usr.bin/gdb/gdb/typeprint.c297
-rw-r--r--gnu/usr.bin/gdb/gdb/typeprint.h21
-rw-r--r--gnu/usr.bin/gdb/gdb/utils.c1547
-rw-r--r--gnu/usr.bin/gdb/gdb/valarith.c969
-rw-r--r--gnu/usr.bin/gdb/gdb/valops.c1819
-rw-r--r--gnu/usr.bin/gdb/gdb/valprint.c1063
-rw-r--r--gnu/usr.bin/gdb/gdb/valprint.h40
-rw-r--r--gnu/usr.bin/gdb/gdb/value.h502
-rw-r--r--gnu/usr.bin/gdb/gdb/values.c1502
-rw-r--r--gnu/usr.bin/gdb/gdb/version.c3
-rw-r--r--gnu/usr.bin/gdb/gdb/wait.h38
-rw-r--r--gnu/usr.bin/gdb/gdb/xm.h31
-rw-r--r--gnu/usr.bin/gdb/getpagesize.h25
-rw-r--r--gnu/usr.bin/gdb/infcmd.c1204
-rw-r--r--gnu/usr.bin/gdb/inferior.h142
-rw-r--r--gnu/usr.bin/gdb/inflow.c569
-rw-r--r--gnu/usr.bin/gdb/infrun.c1459
-rw-r--r--gnu/usr.bin/gdb/kgdb_proto.h63
-rw-r--r--gnu/usr.bin/gdb/libiberty/COPYING.LIB481
-rw-r--r--gnu/usr.bin/gdb/libiberty/Makefile13
-rw-r--r--gnu/usr.bin/gdb/libiberty/README.FreeBSD7
-rw-r--r--gnu/usr.bin/gdb/libiberty/alloca-conf.h11
-rw-r--r--gnu/usr.bin/gdb/libiberty/argv.c332
-rw-r--r--gnu/usr.bin/gdb/libiberty/basename.c56
-rw-r--r--gnu/usr.bin/gdb/libiberty/concat.c118
-rw-r--r--gnu/usr.bin/gdb/libiberty/config.h1
-rw-r--r--gnu/usr.bin/gdb/libiberty/cplus-dem.c2669
-rw-r--r--gnu/usr.bin/gdb/libiberty/fdmatch.c71
-rw-r--r--gnu/usr.bin/gdb/libiberty/getopt.c750
-rw-r--r--gnu/usr.bin/gdb/libiberty/getopt1.c180
-rw-r--r--gnu/usr.bin/gdb/libiberty/ieee-float.c150
-rw-r--r--gnu/usr.bin/gdb/libiberty/ieee-float.h65
-rw-r--r--gnu/usr.bin/gdb/libiberty/obstack.c460
-rw-r--r--gnu/usr.bin/gdb/libiberty/sigsetmask.c44
-rw-r--r--gnu/usr.bin/gdb/libiberty/spaces.c67
-rw-r--r--gnu/usr.bin/gdb/libiberty/strerror.c811
-rw-r--r--gnu/usr.bin/gdb/libiberty/strsignal.c634
-rw-r--r--gnu/usr.bin/gdb/libiberty/xmalloc.c58
-rw-r--r--gnu/usr.bin/gdb/main.c2241
-rw-r--r--gnu/usr.bin/gdb/mmalloc/Makefile10
-rw-r--r--gnu/usr.bin/gdb/mmalloc/README.FreeBSD7
-rw-r--r--gnu/usr.bin/gdb/mmalloc/attach.c218
-rw-r--r--gnu/usr.bin/gdb/mmalloc/detach.c71
-rw-r--r--gnu/usr.bin/gdb/mmalloc/keys.c66
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mcalloc.c53
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mfree.c247
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmalloc.c334
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmalloc.h390
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmalloc.texi258
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmap-sup.c144
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmcheck.c196
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmemalign.c64
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmstats.c46
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mmtrace.c166
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mrealloc.c160
-rw-r--r--gnu/usr.bin/gdb/mmalloc/mvalloc.c40
-rw-r--r--gnu/usr.bin/gdb/mmalloc/sbrk-sup.c96
-rw-r--r--gnu/usr.bin/gdb/ngdb.i386/Makefile27
-rw-r--r--gnu/usr.bin/gdb/obstack.c313
-rw-r--r--gnu/usr.bin/gdb/readline/ChangeLog98
-rw-r--r--gnu/usr.bin/gdb/readline/Makefile.gnu114
-rw-r--r--gnu/usr.bin/gdb/readline/chardefs.h50
-rw-r--r--gnu/usr.bin/gdb/readline/emacs_keymap.c472
-rw-r--r--gnu/usr.bin/gdb/readline/funmap.c217
-rw-r--r--gnu/usr.bin/gdb/readline/history.c1462
-rw-r--r--gnu/usr.bin/gdb/readline/history.h108
-rw-r--r--gnu/usr.bin/gdb/readline/keymaps.c172
-rw-r--r--gnu/usr.bin/gdb/readline/keymaps.h53
-rw-r--r--gnu/usr.bin/gdb/readline/readline.c5557
-rw-r--r--gnu/usr.bin/gdb/readline/readline.h161
-rw-r--r--gnu/usr.bin/gdb/readline/vi_keymap.c484
-rw-r--r--gnu/usr.bin/gdb/readline/vi_mode.c875
-rw-r--r--gnu/usr.bin/gdb/remote-sl.c10
-rw-r--r--gnu/usr.bin/gdb/remote.c626
-rw-r--r--gnu/usr.bin/gdb/source.c1166
-rw-r--r--gnu/usr.bin/gdb/stab.def115
-rw-r--r--gnu/usr.bin/gdb/stack.c960
-rw-r--r--gnu/usr.bin/gdb/symmisc.c584
-rw-r--r--gnu/usr.bin/gdb/symseg.h523
-rw-r--r--gnu/usr.bin/gdb/symtab.c2473
-rw-r--r--gnu/usr.bin/gdb/symtab.h384
-rw-r--r--gnu/usr.bin/gdb/utils.c1096
-rw-r--r--gnu/usr.bin/gdb/valarith.c690
-rw-r--r--gnu/usr.bin/gdb/valops.c1418
-rw-r--r--gnu/usr.bin/gdb/valprint.c1430
-rw-r--r--gnu/usr.bin/gdb/value.h212
-rw-r--r--gnu/usr.bin/gdb/values.c1059
-rw-r--r--gnu/usr.bin/gdb/version.c20
-rw-r--r--gnu/usr.bin/gdb/wait.h81
-rw-r--r--gnu/usr.bin/gdb/xgdb/Makefile33
-rw-r--r--gnu/usr.bin/gdb/xgdb/xgdb.c700
320 files changed, 148765 insertions, 53565 deletions
diff --git a/gnu/usr.bin/gdb/COPYING b/gnu/usr.bin/gdb/COPYING
index 9a1703758111..a43ea2126fb6 100644
--- a/gnu/usr.bin/gdb/COPYING
+++ b/gnu/usr.bin/gdb/COPYING
@@ -1,38 +1,40 @@
-
GNU GENERAL PUBLIC LICENSE
- Version 1, February 1989
+ Version 2, June 1991
- Copyright (C) 1989 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
+ Copyright (C) 1989, 1991 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
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU 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.
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+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.
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), 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
+ For example, if you distribute copies of 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.
+source code. And you must show them these terms so they know 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,
@@ -45,120 +47,207 @@ 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.
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
The precise terms and conditions for copying, distribution and
modification follow.
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.
+ 0. This License 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 derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 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 License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+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.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary 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
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
- 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
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 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 Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (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.
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing 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 for copying, distributing or modifying
+the Program or works based on it.
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.
+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.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
- 7. The Free Software Foundation may publish revised and/or new versions
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. 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
+specifies a version number of this 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
+this 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
+ 10. 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
@@ -168,7 +257,7 @@ of promoting the sharing and reuse of software generally.
NO WARRANTY
- 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ 11. 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
@@ -178,7 +267,7 @@ 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
+ 12. 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
@@ -193,22 +282,21 @@ POSSIBILITY OF SUCH DAMAGES.
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.
+possible use to the public, 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.
+ 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.
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -224,26 +312,28 @@ 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 version 69, Copyright (C) 19yy 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.
+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:
+necessary. Here is 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.
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
-That's all there is to it!
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/gdb/COPYING.LIB b/gnu/usr.bin/gdb/COPYING.LIB
new file mode 100644
index 000000000000..eb685a5ec981
--- /dev/null
+++ b/gnu/usr.bin/gdb/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 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.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), 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 library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ 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.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library 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 Library
+specifies a version number of this 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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; 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.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/gnu/usr.bin/gdb/ChangeLog b/gnu/usr.bin/gdb/ChangeLog
deleted file mode 100644
index 1f2342b797a7..000000000000
--- a/gnu/usr.bin/gdb/ChangeLog
+++ /dev/null
@@ -1,4887 +0,0 @@
-Thu Feb 8 01:11:55 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
-
- * GDB 3.5 released.
-
- * version.c: Change version number to 3.5
-
-Tue Feb 6 15:58:06 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
-
- * m-hp9k320.h: define ATTACH_DETACH.
- hp9k320-dep.c [ATTACH_DETACH]: New code.
-
-Thu Feb 1 17:43:00 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
-
- * valprint.c (is_nan, val_print): Use char * not void *.
-
- * symmisc.c (print_symbol): Print newline after label.
-
-Tue Jan 30 15:35:52 1990 Jim Kingdon (kingdon at albert.ai.mit.edu)
-
- * Makefile.dist (READLINE): Add {readline,history}.texinfo.
-
- * m-merlin.h: Put in clarifying comments about SHELL_FILE.
- config.gdb (merlin): Explain about /usr/local/lib/gdb-sh.
-
-Sat Jan 27 02:30:27 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
-
- * version.c: Change version number to 3.5alpha.1.
-
- * dbxread.c (process_one_symbol): Compare context_stack_depth
- with !VARIABLES_INSIDE_BLOCK, not VARIABLES_INSIDE_BLOCK.
-
-Fri Jan 26 01:21:51 1990 Jim Kingdon (kingdon at mole.ai.mit.edu)
-
- * main.c [ALIGN_STACK_ON_STARTUP]: New code.
- m-i386.h: Define ALIGN_STACK_ON_STARTUP.
-
- * m-merlin.h (NO_SIGINTERRUPT, SHELL_FILE): Define.
-
- * umax-dep.c (exec_file_command): Add commas to call to
- read_section_hdr.
-
-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 ==> ).
-
- * 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.
-
-
-Local Variables:
-mode: indented-text
-eval: (auto-fill-mode 1)
-left-margin: 8
-fill-column: 74
-version-control: never
-End:
-
- 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.
-
-Local Variables:
-mode: indented-text
-left-margin: 8
-fill-column: 74
-version-control: never
-End:
diff --git a/gnu/usr.bin/gdb/Gdbinit b/gnu/usr.bin/gdb/Gdbinit
deleted file mode 100644
index bcacd5dc7e84..000000000000
--- a/gnu/usr.bin/gdb/Gdbinit
+++ /dev/null
@@ -1,15 +0,0 @@
-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/gnu/usr.bin/gdb/Makefile b/gnu/usr.bin/gdb/Makefile
index 550ed07a7575..8536444cda0b 100644
--- a/gnu/usr.bin/gdb/Makefile
+++ b/gnu/usr.bin/gdb/Makefile
@@ -1,38 +1,3 @@
-# @(#)Makefile 6.4 (Berkley) 5/6/91
+SUBDIR= bfd libiberty mmalloc gdb
-PROG= gdb
-GDBSRCS= blockframe.c breakpoint.c command.c copying.c core.c \
- cplus-dem.c dbxread.c environ.c eval.c expprint.c \
- expread.y findvar.c infcmd.c inflow.c infrun.c \
- main.c obstack.c printcmd.c regex.c remote.c \
- remote-sl.c source.c stack.c symmisc.c symtab.c \
- utils.c valarith.c valops.c valprint.c values.c \
- version.c
-READLINESRCS= funmap.c history.c keymaps.c readline.c
-SRCS= $(CONFIGSRCS) $(GDBSRCS) $(READLINESRCS) init.c
-CFLAGS+= -I. -I$(.CURDIR) -I$(.CURDIR)/config -I$(.CURDIR)/readline \
- -DHAVE_VPRINTF -DVI_MODE -DKERNELDEBUG -DNEWVM
-LDADD= -ltermcap
-YFLAGS=
-.PATH: $(.CURDIR)/config $(.CURDIR)/readline
-
-depend:
-
-.include "config/Makefile.$(MACHINE)"
-.include <bsd.prog.mk>
-
-$(OBJS): param.h
-
-#
-# Generate the constructor
-#
-init.c: $(CONFIGSRCS) $(GDBSRCS) $(READLINESRCS)
- -((cd $(.CURDIR)/config; \
- egrep -h '^_initialize_[^ ]* *\(\)' $(CONFIGSRCS)); \
- (cd $(.CURDIR); egrep -h '^_initialize_[^ ]* *\(\)' $(GDBSRCS)); \
- (cd $(.CURDIR)/readline; \
- egrep -h '^_initialize_[^ ]* *\(\)' $(READLINESRCS))) | \
- (echo 'void initialize_all_files () {'; sed -e 's/$$/;/'; echo '}') \
- > init.c
-
-CLEANFILES+= init.c param.h
+.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/gdb/Makefile.dist b/gnu/usr.bin/gdb/Makefile.dist
deleted file mode 100644
index 3cbc91f9786f..000000000000
--- a/gnu/usr.bin/gdb/Makefile.dist
+++ /dev/null
@@ -1,371 +0,0 @@
-/* This file should be run through the C preprocessor by config.gdb
- to produce the Makefile. */
-
-/* Define this to xgdb if you want to compile xgdb as well as gdb. */
-XGDB=
-/* Place to install binaries. */
-bindir=/usr/local/bin
-/* Place to install X binaries. */
-xbindir=$(bindir)
-
-/* 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=gcc -traditional */
-CC=cc
-
-/* 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 -v
-/* 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}
-
-/* If you are using the GNU C library, uncomment the following line. */
-/* HAVE_VPRINTF_DEFINE = -DHAVE_VPRINTF */
-
-/* -I. for "#include <obstack.h>". Possibly regex.h also. */
-
-/* M_CFLAGS, if defined, has system-dependent CFLAGS. */
-#if !defined(M_CFLAGS)
-#define M_CFLAGS
-#endif
-
-/* CFLAGS for both GDB and readline. */
-GLOBAL_CFLAGS = -g M_CFLAGS
-CFLAGS = -I. ${HAVE_VPRINTF_DEFINE} ${GLOBAL_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
- you must at the same time define OBSTACK1 as "obstack.o"
- so that the dependencies work right. Similarly with REGEX and "regex.o".
- 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 */
-OBSTACK = obstack.o
-OBSTACK1 = obstack.o
-
-#ifdef M_REGEX
-REGEX = M_REGEX
-REGEX1 = M_REGEX
-#else
-REGEX =
-REGEX1 =
-#endif
-
-#ifdef M_ALLOCA
-ALLOCA = M_ALLOCA
-ALLOCA1 = M_ALLOCA
-#else
-ALLOCA =
-ALLOCA1 =
-#endif
-
-/*
- define this to be "malloc.o" if you want to use the gnu malloc routine
- (useful for debugging memory allocation problems in gdb). Otherwise, leave
- it blank. */
-/* GNU_MALLOC = */
-GNU_MALLOC = malloc.o
-
-/* Flags to be used in compiling malloc.o
- Specify range checking for storage allocation. */
-/* MALLOC_FLAGS = ${CFLAGS} */
-MALLOC_FLAGS = ${CFLAGS} -Drcheck -Dbotch=fatal_dump_core -DMSTATS
-
-/* Define SYSV if compiling on a system V or HP machine. */
-#ifdef M_SYSV
-SYSV_DEFINE = -DSYSV
-#else
-SYSV_DEFINE =
-#endif
-
-/* MUNCH_DEFINE should be -DSYSV if have System V-style nm,
- or null if have BSD-style nm. */
-#ifdef M_BSD_NM
-MUNCH_DEFINE =
-#else
-MUNCH_DEFINE = ${SYSV_DEFINE}
-#endif
-
-/* Flags that describe where you can find the termcap library.
- You may need to make other arrangements for USG. */
-TERMCAP = -ltermcap
-
-/* M_CLIBS, if defined, has system-dependent libs
- For example, -lPW for System V to get alloca(). */
-#ifndef M_CLIBS
-#define M_CLIBS
-#endif
-CLIBS = ${ADD_FILES} ${TERMCAP} M_CLIBS
-
-ADD_FILES = ${OBSTACK} ${REGEX} ${ALLOCA} ${GNU_MALLOC}
-ADD_DEPS = ${OBSTACK1} ${REGEX1} ${ALLOCA1} ${GNU_MALLOC}
-
-SFILES = blockframe.c breakpoint.c dbxread.c coffread.c command.c core.c \
- environ.c eval.c expprint.c findvar.c infcmd.c inflow.c infrun.c \
- kdb-start.c main.c printcmd.c \
- remote.c source.c stack.c standalone.c stuff.c symmisc.c symtab.c \
- utils.c valarith.c valops.c valprint.c values.c version.c expread.y \
- xgdb.c
-
-DEPFILES = umax-dep.c gould-dep.c default-dep.c sun3-dep.c \
- sparc-dep.c hp9k320-dep.c hp300bsd-dep.c news-dep.c i386-dep.c \
- symmetry-dep.c convex-dep.c altos-dep.c isi-dep.c pyr-dep.c
-
-PINSNS = gld-pinsn.c i386-pinsn.c sparc-pinsn.c vax-pinsn.c m68k-pinsn.c \
- ns32k-pinsn.c convex-pinsn.c pyr-pinsn.c
-
-HFILES = command.h defs.h environ.h expression.h frame.h getpagesize.h \
- inferior.h symseg.h symtab.h value.h wait.h \
- a.out.encap.h a.out.gnu.h stab.gnu.h
-
-OPCODES = m68k-opcode.h pn-opcode.h sparc-opcode.h npl-opcode.h vax-opcode.h \
- ns32k-opcode.h convex-opcode.h pyr-opcode.h
-
-MFILES = m-hp9k320.h m-hp300bsd.h m-i386.h m-i386gas.h \
- m-i386-sv32.h m-i386g-sv32.h m-isi.h m-merlin.h \
- m-altos.h m-news.h m-newsos3.h m-npl.h m-pn.h \
- m-sparc.h m-sun2.h m-sun3.h m-sun2os4.h \
- m-sun3os4.h m-sun4os4.h m-umax.h m-vax.h m-symmetry.h m-convex.h \
- m-pyr.h
-
-/* This list of files really shouldn't be in this makefile, but I can't think
- of any good way to get the readline makefile to tell us what files
- to put in our tarfile. */
-READLINE = readline.c history.c funmap.c \
- emacs_keymap.c vi_keymap.c vi_mode.c keymaps.c \
- readline.h history.h keymaps.h chardefs.h \
- inc-readline.texinfo inc-history.texinfo \
- readline.texinfo history.texinfo \
- Makefile ChangeLog
-
-REMOTE_EXAMPLES = remote-sa.m68k.shar remote-multi.shar
-
-POSSLIBS = obstack.h obstack.c regex.c regex.h malloc.c alloca.c
-
-TESTS = testbpt.c testfun.c testrec.c testreg.c testregs.c
-
-OTHERS = Makefile.dist createtags munch config.gdb ChangeLog README TAGS \
- gdb.texinfo .gdbinit COPYING expread.tab.c stab.def \
- XGDB-README copying.c Projects Convex.notes copying.awk hp-include
-
-TAGFILES = ${SFILES} ${DEPFILES} ${PINSNS} ${HFILES} ${OPCODES} ${MFILES} \
- ${POSSLIBS}
-TARFILES = ${TAGFILES} ${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 symmisc.o coffread.o dbxread.o infcmd.o infrun.o remote.o \
- command.o utils.o expread.o expprint.o pinsn.o environ.o version.o \
- copying.o ${READLINEOBS}
-
-TSOBS = core.o inflow.o dep.o
-
-NTSOBS = standalone.o
-
-TSSTART = /lib/crt0.o
-
-NTSSTART = kdb-start.o
-
-RL_LIB = readline/libreadline.a
-
-/* Do some fancy trickery to produce a line like
- -DM_MAKEDEFINE="-DM_SYSV -DM_BSD_NM".
-*/
-MD=M_MAKEDEFINE
-
-/* Avoid funny things that Sun's make throws in for us. */
-/* TARGET_ARCH is supposed to get around it putting in the machine type.
- If the "things" up there really is plural, we'll need to do something
- else as well. */
-/*.c.o:
- ${CC} -c ${CFLAGS} $< */
-TARGET_ARCH=
-
-all: gdb $(XGDB)
-
-install: gdb $(XGDB)
- cp gdb $(bindir)/gdb.new
- mv $(bindir)/gdb.new $(bindir)/gdb
- -if [ "$(XGDB)" = xgdb ]; then \
- cp xgdb $(xbindir)/xgdb.new; \
- mv $(xbindir)/xgdb.new $(xbindir)xgdb; \
- fi
-
-gdb : $(OBS) $(TSOBS) ${ADD_DEPS} ${RL_LIB}
- rm -f init.c
- ./munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) > init.c
- ${CC-LD} $(LDFLAGS) -o gdb init.c $(OBS) $(TSOBS) ${RL_LIB} $(CLIBS)
-
-/* This is useful when debugging GDB, because Unix doesn'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". */
-gdb1 : gdb
- cp gdb gdb1
-
-Makefile : Makefile.dist
- cp Makefile.dist tmp.c
- $(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=$(MD)"
- -rm tmp.c
-/* This did not work-- -Usparc became "-Usparc" became "-Usparc.
- Or something like that. */
-/* $(CC) -E >Makefile tmp.c $(MD) "-DM_MAKEDEFINE=\"$(MD)\"" */
-
-xgdb : $(OBS) $(TSOBS) xgdb.o ${ADD_DEPS} ${RL_LIB}
- rm -f init.c
- ./munch ${MUNCH_DEFINE} $(OBS) $(TSOBS) xgdb.o > init.c
- $(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
- -lXaw -lXmu -lXt -lX11 ${RL_LIB} $(CLIBS)
-
-/* Old (pre R3) xgdb comp.
- $(CC-LD) $(LDFLAGS) -o xgdb init.c $(OBS) $(TSOBS) xgdb.o \
- -lXaw -lXt -lX11 $(CLIBS) */
-
-kdb : $(NTSSTART) $(OBS) $(NTSOBS) ${ADD_DEPS} ${RL_LIB}
- rm -f init.c
- ./munch ${MUNCH_DEFINE} $(OBS) $(NTSOBS) > init.c
- $(CC) $(LDFLAGS) -c init.c $(CLIBS)
- ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o ${RL_LIB} -lc $(CLIBS)
-
-/* If it can figure out the appropriate order, createtags will make sure
- that the proper m-*, *-dep, *-pinsn, and *-opcode files come first
- in the tags list. It will attempt to do the same for dbxread.c and
- coffread.c. This makes using M-. on machine dependent routines much
- easier. */
-
-TAGS: ${TAGFILES}
- createtags ${TAGFILES}
-tags: TAGS
-
-gdb.tar: ${TARFILES}
- rm -f gdb.tar
- mkdir dist-gdb
- cd dist-gdb ; for i in ${TARFILES} ; do ln -s ../$$i . ; done
- mkdir dist-gdb/readline
- cd dist-gdb/readline ; for i in ${READLINE} ; do ln -s ../../readline/$$i . ; done
- tar chf gdb.tar dist-gdb
- rm -rf dist-gdb
-
-/* Remove gdb.tar.Z so stupid compress doesn't ask whether we want to
- overwrite it. compress -f is not what we want, because we do want
- to know if compress would not make it smaller. */
-gdb.tar.Z: gdb.tar
- if [ -f gdb.tar.Z ]; then rm -f gdb.tar.Z; else true; fi
- compress gdb.tar
-
-clean:
- rm -f ${OBS} ${TSOBS} ${NTSOBS} ${OBSTACK} ${REGEX} ${GNU_MALLOC}
- rm -f init.c init.o
- rm -f xgdb.o xgdb
- 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 dep.c opcode.h param.h pinsn.c config.status
- rm -f y.output yacc.acts yacc.tmp
- rm -f ${TESTS} Makefile
-
-realclean: clean
- rm -f expread.tab.c TAGS
- rm -f dep.c opcode.h param.h pinsn.c config.status
- rm -f Makefile
-
-xgdb.o : defs.h param.h symtab.h frame.h
-
-/* Make copying.c from COPYING */
-copying.c : COPYING copying.awk
- awk -f copying.awk < COPYING > copying.c
-
-expread.tab.c : expread.y
- @echo 'Expect 4 shift/reduce conflict.'
- ${YACC} expread.y
- mv y.tab.c expread.tab.c
-
-expread.o : expread.tab.c defs.h param.h symtab.h frame.h expression.h
- $(CC) -c ${CFLAGS} expread.tab.c
- mv expread.tab.o expread.o
-
-readline/libreadline.a : force_update
- cd readline ; ${MAKE} "SYSV=${SYSV_DEFINE}" \
- "DEBUG_FLAGS=${GLOBAL_CFLAGS}" "CC=${CC}" libreadline.a
-
-force_update :
-
-/* Only useful if you are using the gnu malloc routines. */
-malloc.o : malloc.c
- ${CC} -c ${MALLOC_FLAGS} malloc.c
-
-/* dep.o depends on config.status in case someone reconfigures gdb out
- from under an already compiled gdb. */
-dep.o : dep.c config.status defs.h param.h frame.h inferior.h obstack.h \
- a.out.encap.h
-
-/* pinsn.o depends on config.status in case someone reconfigures gdb out
- from under an already compiled gdb. */
-pinsn.o : pinsn.c config.status defs.h param.h symtab.h obstack.h symseg.h \
- frame.h opcode.h
-
-/* The rest of this is a standard dependencies list (hand edited output of
- cpp -M). It does not include dependencies of .o files on .c files. */
-/* All files which depend on config.status also depend on param.h in case
- someone reconfigures gdb out from under an already compiled gdb. */
-blockframe.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
-breakpoint.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
-coffread.o : defs.h param.h config.status
-command.o : command.h defs.h
-core.o : defs.h param.h config.status a.out.encap.h
-dbxread.o : param.h config.status defs.h symtab.h obstack.h symseg.h a.out.encap.h \
- stab.gnu.h
-environ.o : environ.h
-eval.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h expression.h
-expprint.o : defs.h symtab.h obstack.h symseg.h param.h config.status expression.h
-findvar.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h value.h
-infcmd.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h inferior.h \
- environ.h value.h
-inflow.o : defs.h param.h config.status frame.h inferior.h
-infrun.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h inferior.h \
- wait.h
-kdb-start.o : defs.h param.h config.status
-main.o : defs.h command.h param.h config.status
-malloc.o : getpagesize.h
-obstack.o : obstack.h
-printcmd.o : defs.h param.h config.status frame.h symtab.h obstack.h symseg.h value.h \
- expression.h
-regex.o : regex.h
-remote.o : defs.h param.h config.status frame.h inferior.h wait.h
-source.o : defs.h symtab.h obstack.h symseg.h param.h config.status
-stack.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h
-standalone.o : defs.h param.h config.status symtab.h obstack.h symseg.h frame.h \
- inferior.h wait.h
-symmisc.o : defs.h symtab.h obstack.h symseg.h obstack.h
-symtab.o : defs.h symtab.h obstack.h symseg.h param.h config.status obstack.h
-utils.o : defs.h param.h config.status
-valarith.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h expression.h
-valops.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h frame.h \
- inferior.h
-valprint.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h
-values.o : defs.h param.h config.status symtab.h obstack.h symseg.h value.h
-
-robotussin.h : getpagesize.h
-symtab.h : obstack.h symseg.h
-a.out.encap.h : a.out.gnu.h
-
diff --git a/gnu/usr.bin/gdb/Projects b/gnu/usr.bin/gdb/Projects
deleted file mode 100644
index f38f6c74e959..000000000000
--- a/gnu/usr.bin/gdb/Projects
+++ /dev/null
@@ -1,114 +0,0 @@
-
- Suggested projects for aspiring or current GDB hackers
- ======================================================
-
- (You should probably chat with kingdon@ai.mit.edu to make sure that
- no one else is doing the project you chose).
-
-Add watchpoints (break if a memory location changes). This would
-usually have to involve constant single stepping, but occasionally
-there is operating system support which gdb should be able to cleanly
-use (e.g. on the 80386, there are 4 debug registers. By ptracing an
-address into them, you can get a trap on writes or on reads and
-writes).
-
-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.
-
-Make "handle" understand symbolic signal names.
-
-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.
-
-A standalone version of gdb on the i386 exists. Anyone who wants to
-do some serious working cleaning it up and making it a general
-standalone gdb should contact pace@wheaties.ai.mit.edu.
-
-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.
-
-Work out some method of saving breakpoints across the reloading of an
-executable. Probably this should be by saving the commands by which
-the breakpoints were set and re-executing them (as text locations may
-change).
-
-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.
-
-Problem in xgdb; the readline library needs the terminal in CBREAK
-mode for command line editing, but this makes it difficult to dispatch
-on button presses. Possible solution: use a define to replace getc in
-readline.c with a routine that does button dispatches. You should
-probably see XGDB-README before you fiddle with XGDB. Also, someone
-is implementing a new xgdb; it may not be worth while fiddling with
-the old one.
-
-# Local Variables:
-# mode: text
-# End:
diff --git a/gnu/usr.bin/gdb/README.FreeBSD b/gnu/usr.bin/gdb/README.FreeBSD
new file mode 100644
index 000000000000..75a30b2cb431
--- /dev/null
+++ b/gnu/usr.bin/gdb/README.FreeBSD
@@ -0,0 +1,15 @@
+This is a greatly pared down version of GDB-4.12 for FreeBSD 1.1.5 that
+supports debugging of shared executables and the new a.out format.
+
+I've collapsed some of the directories and removed lots of files from others.
+All that's included is those necessary to compile on FreeBSD 1.1.5, this was
+to keep the replacement for GDB-3 compact since none of the multiple
+architecture stuff is used. All the documentation has been put in the doc/
+directory.
+
+A full port of each library will probably be done for FreeBSD 2.0 and
+included as system libraries so that other build tools can share them.
+At that time a more complete port of GDB-4 will be done that allows
+configuration for different systems and uses the full libraries.
+
+paul@freefall.cdrom.com
diff --git a/gnu/usr.bin/gdb/README.gnu b/gnu/usr.bin/gdb/README.gnu
deleted file mode 100644
index fa54dec236fd..000000000000
--- a/gnu/usr.bin/gdb/README.gnu
+++ /dev/null
@@ -1,142 +0,0 @@
-This is GDB, the GNU source-level debugger, presently running under un*x.
-
-Before compiling GDB, you must tell GDB what kind of machine you are
-running on. To do this, type `config.gdb machine', where machine is
-something like `vax' or `sun2'. For a list of valid machine types,
-type `config.gdb'.
-
-Normally config.gdb edits the makefile as necessary. If you have to
-edit the makefile on a standard machine listed in config.gdb this
-should be considered a bug and reported as such.
-
-Once these files are set up, just `make' will do everything,
-producing an executable `gdb' in this directory.
-
-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.
-The gdb.texinfo file requires the texinfo-format-buffer command from
-emacs 18.55 or later.
-
-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), 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 -gg format...
-
-Currently GDB version 3.x does *not* support GCC's -gg format. This
-is because it (in theory) has fast enough startup on dbx debugging
-format object files that -gg format is unnecessary (and hence
-undesirable, since it wastes space and processing power in gcc). I
-would like to hear people's opinions on the amount of time currently
-spent in startup; is it fast enough?
-
-About remote debugging...
-
-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.
-
-About reporting bugs...
-
-The correct address for reporting bugs found with gdb is
-"bug-gdb@prep.ai.mit.edu". Please send all bugs to that address.
-
-About xgdb...
-
-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. 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.
-Comments on this mode are welcome.
-
-About the machine-dependent files...
-
-m-<machine>.h (param.h is a link to this file).
-This file contains macro definitions that express information
-about the machine's registers, stack frame format and instructions.
-
-<machine>-opcode.h (opcode.h is a link to this file).
-<machine>-pinsn.c (pinsn.c is a link to this file).
-These files contain the information necessary to print instructions
-for your cpu type.
-
-<machine>-dep.c (dep.c is a link to this file).
-Those routines which provide a low level interface to ptrace and which
-tend to be machine-dependent. (The machine-independent routines are in
-`infrun.c' and `inflow.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.
-
-Please try to avoid making machine-specific changes to
-machine-independent files (i.e. all files except "param.h" and
-"dep.c". "pinsn.c" and "opcode.h" are processor-specific but not
-operating system-dependent). 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
-param.h) rather than something like #if defined(vax) or #if
-defined(SYSV).
-
-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, if something needs to be
-changed in read_inferior_memory, it is very painful because there is a
-copy in every dep.c file. The correct way to do this is to put (in
-this case) the standard ptrace interfaces in a separate file ptrace.c,
-which is used by all systems which have ptrace. ptrace.c would deal
-with variations between systems the same way any system-independent
-file would (hooks, #if defined, etc.).
-
-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.
-
-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 more details.
-
diff --git a/gnu/usr.bin/gdb/VERSION b/gnu/usr.bin/gdb/VERSION
new file mode 100644
index 000000000000..b849ff8ebf1f
--- /dev/null
+++ b/gnu/usr.bin/gdb/VERSION
@@ -0,0 +1 @@
+4.11
diff --git a/gnu/usr.bin/gdb/XGdbinit.samp b/gnu/usr.bin/gdb/XGdbinit.samp
deleted file mode 100644
index a99f10695606..000000000000
--- a/gnu/usr.bin/gdb/XGdbinit.samp
+++ /dev/null
@@ -1,15 +0,0 @@
-button "show" push-to-file %S
-button "back" pop-file
-button "break in" break %S
-button "break at" break %l
-button delete delete %b%e
-button backtrace
-button up
-button down
-button print print %E
-button print* print *(%E)
-button next
-button step
-button "do upto" until %l%e
-button finish
-button continue cont%e
diff --git a/gnu/usr.bin/gdb/Xgdb.ad b/gnu/usr.bin/gdb/Xgdb.ad
deleted file mode 100644
index 5f9fe9920b49..000000000000
--- a/gnu/usr.bin/gdb/Xgdb.ad
+++ /dev/null
@@ -1,8 +0,0 @@
-Xgdb*geometry: 580x874-0+28
-Xgdb*src*scrollVertical: whenneeded
-Xgdb*src*scrollHorizontal: whenneeded
-Xgdb*src*wrap: never
-Xgdb*src*editType: read
-Xgdb*frame.buttons.allowResize: true
-Xgdb*frame.buttons.skipAdjust: true
-Xgdb*frame*showGrip: false
diff --git a/gnu/usr.bin/gdb/bfd/COPYING b/gnu/usr.bin/gdb/bfd/COPYING
new file mode 100644
index 000000000000..a43ea2126fb6
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 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 licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU 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. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), 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 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 show them these terms so they know 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.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License 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 derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 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 License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+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.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary 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
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 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 Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing 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 for copying, distributing or modifying
+the Program or works based on it.
+
+ 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.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. 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 this 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
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. 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
+
+ 11. 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.
+
+ 12. 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
+
+ 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 the public, 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 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 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) 19yy 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 is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/gdb/bfd/Makefile b/gnu/usr.bin/gdb/bfd/Makefile
new file mode 100644
index 000000000000..ea29afed0d86
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/Makefile
@@ -0,0 +1,17 @@
+LIB = bfd
+SRCS = archive.c archures.c bfd.c cache.c coffgen.c core.c ctor.c \
+ format.c init.c libbfd.c opncls.c reloc.c seclet.c section.c syms.c \
+ targets.c ecoff.c elf.c srec.c freebsd386.c aout32.c stab-syms.c \
+ cpu-i386.c trad-core.c
+
+CFLAGS+= -I$(.CURDIR)/. -I$(.CURDIR)/../gdb/.
+CFLAGS+= -DDEFAULT_VECTOR=freebsd386_vec -DSELECT_VECS='&freebsd386_vec' \
+ -DSELECT_ARCHITECTURES='bfd_i386_arch' -DTRAD_CORE
+
+NOPROFILE=no
+NOPIC=no
+
+install:
+ @echo -n
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/gdb/bfd/README.FreeBSD b/gnu/usr.bin/gdb/bfd/README.FreeBSD
new file mode 100644
index 000000000000..204119c1af74
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/README.FreeBSD
@@ -0,0 +1,7 @@
+This is a greatly pared down libbfd directory. Only what's required to build
+gdb-4.12 on FreeBSD was kept.
+
+This is temporary. In FreeBSD 2.0 a fully ported libbfd will likely appear
+as a system library for use by all the build tools.
+
+paul@freefall.cdrom.com
diff --git a/gnu/usr.bin/gdb/bfd/VERSION b/gnu/usr.bin/gdb/bfd/VERSION
new file mode 100644
index 000000000000..8bbe6cf74a1e
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/VERSION
@@ -0,0 +1 @@
+2.2
diff --git a/gnu/usr.bin/gdb/bfd/aout-target.h b/gnu/usr.bin/gdb/bfd/aout-target.h
new file mode 100644
index 000000000000..65a22fff9b04
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/aout-target.h
@@ -0,0 +1,429 @@
+/* Define a target vector and some small routines for a variant of a.out.
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+/*#include "libaout.h"*/
+
+extern CONST struct reloc_howto_struct * NAME(aout,reloc_type_lookup) ();
+
+/* Set parameters about this a.out file that are machine-dependent.
+ This routine is called from some_aout_object_p just before it returns. */
+#ifndef MY_callback
+static bfd_target *
+DEFUN(MY(callback),(abfd),
+ bfd *abfd)
+{
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ /* Calculate the file positions of the parts of a newly read aout header */
+ obj_textsec (abfd)->_raw_size = N_TXTSIZE(*execp);
+
+ /* The virtual memory addresses of the sections */
+ obj_textsec (abfd)->vma = N_TXTADDR(*execp);
+ obj_datasec (abfd)->vma = N_DATADDR(*execp);
+ obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
+
+ /* The file offsets of the sections */
+ obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
+ obj_datasec (abfd)->filepos = N_DATOFF (*execp);
+
+ /* The file offsets of the relocation info */
+ obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
+ obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
+
+ /* The file offsets of the string table and symbol table. */
+ obj_sym_filepos (abfd) = N_SYMOFF (*execp);
+ obj_str_filepos (abfd) = N_STROFF (*execp);
+
+ /* Determine the architecture and machine type of the object file. */
+#ifdef SET_ARCH_MACH
+ SET_ARCH_MACH(abfd, *execp);
+#else
+ bfd_default_set_arch_mach(abfd, DEFAULT_ARCH, 0);
+#endif
+
+ /* Don't set sizes now -- can't be sure until we know arch & mach.
+ Sizes get set in set_sizes callback, later. */
+#if 0
+ adata(abfd).page_size = PAGE_SIZE;
+#ifdef SEGMENT_SIZE
+ adata(abfd).segment_size = SEGMENT_SIZE;
+#else
+ adata(abfd).segment_size = PAGE_SIZE;
+#endif
+ adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+#endif
+
+ return abfd->xvec;
+}
+#endif
+
+#ifndef MY_object_p
+/* Finish up the reading of an a.out file header */
+
+static bfd_target *
+DEFUN(MY(object_p),(abfd),
+ bfd *abfd)
+{
+ struct external_exec exec_bytes; /* Raw exec header from file */
+ struct internal_exec exec; /* Cleaned-up exec header */
+ bfd_target *target;
+
+ if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+ != EXEC_BYTES_SIZE) {
+ bfd_error = wrong_format;
+ return 0;
+ }
+
+#ifdef NO_SWAP_MAGIC
+ memcpy (&exec.a_info, exec_bytes.e_info, sizeof(exec.a_info));
+#else
+ exec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info);
+#endif /* NO_SWAP_MAGIC */
+
+ if (N_BADMAG (exec)) return 0;
+#ifdef MACHTYPE_OK
+ if (!(MACHTYPE_OK (N_MACHTYPE (exec)))) return 0;
+#endif
+
+ NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, &exec);
+ target = NAME(aout,some_aout_object_p) (abfd, &exec, MY(callback));
+
+#ifdef ENTRY_CAN_BE_ZERO
+ /* The NEWSOS3 entry-point is/was 0, which (amongst other lossage)
+ * means that it isn't obvious if EXEC_P should be set.
+ * All of the following must be true for an executable:
+ * There must be no relocations, the bfd can be neither an
+ * archive nor an archive element, and the file must be executable. */
+
+ if (exec.a_trsize + exec.a_drsize == 0
+ && bfd_get_format(abfd) == bfd_object && abfd->my_archive == NULL)
+ {
+ struct stat buf;
+#ifndef S_IXUSR
+#define S_IXUSR 0100 /* Execute by owner. */
+#endif
+ if (stat(abfd->filename, &buf) == 0 && (buf.st_mode & S_IXUSR))
+ abfd->flags |= EXEC_P;
+ }
+#endif /* ENTRY_CAN_BE_ZERO */
+
+ return target;
+}
+#define MY_object_p MY(object_p)
+#endif
+
+
+#ifndef MY_mkobject
+static boolean
+DEFUN(MY(mkobject),(abfd),
+ bfd *abfd)
+{
+ if (NAME(aout,mkobject)(abfd) == false)
+ return false;
+#if 0 /* Sizes get set in set_sizes callback, later, after we know
+ the architecture and machine. */
+ adata(abfd).page_size = PAGE_SIZE;
+#ifdef SEGMENT_SIZE
+ adata(abfd).segment_size = SEGMENT_SIZE;
+#else
+ adata(abfd).segment_size = PAGE_SIZE;
+#endif
+ adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+#endif
+ return true;
+}
+#define MY_mkobject MY(mkobject)
+#endif
+
+/* Write an object file.
+ Section contents have already been written. We write the
+ file header, symbols, and relocation. */
+
+#ifndef MY_write_object_contents
+static boolean
+DEFUN(MY(write_object_contents),(abfd),
+ bfd *abfd)
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+#if CHOOSE_RELOC_SIZE
+ CHOOSE_RELOC_SIZE(abfd);
+#else
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+#endif
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
+#define MY_write_object_contents MY(write_object_contents)
+#endif
+
+#ifndef MY_set_sizes
+static boolean
+DEFUN(MY(set_sizes),(abfd), bfd *abfd)
+{
+ adata(abfd).page_size = PAGE_SIZE;
+#ifdef SEGMENT_SIZE
+ adata(abfd).segment_size = SEGMENT_SIZE;
+#else
+ adata(abfd).segment_size = PAGE_SIZE;
+#endif
+ adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+ return true;
+}
+#define MY_set_sizes MY(set_sizes)
+#endif
+
+#ifndef MY_backend_data
+static CONST struct aout_backend_data MY(backend_data) = {
+ 0, /* zmagic contiguous */
+ 0, /* text incl header */
+ 0, /* text vma? */
+ MY_set_sizes,
+ 0, /* exec header is counted */
+};
+#define MY_backend_data &MY(backend_data)
+#endif
+
+/* We assume BFD generic archive files. */
+#ifndef MY_openr_next_archived_file
+#define MY_openr_next_archived_file bfd_generic_openr_next_archived_file
+#endif
+#ifndef MY_generic_stat_arch_elt
+#define MY_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#endif
+#ifndef MY_slurp_armap
+#define MY_slurp_armap bfd_slurp_bsd_armap
+#endif
+#ifndef MY_slurp_extended_name_table
+#define MY_slurp_extended_name_table _bfd_slurp_extended_name_table
+#endif
+#ifndef MY_write_armap
+#define MY_write_armap bsd_write_armap
+#endif
+#ifndef MY_truncate_arname
+#define MY_truncate_arname bfd_bsd_truncate_arname
+#endif
+
+/* No core file defined here -- configure in trad-core.c separately. */
+#ifndef MY_core_file_failing_command
+#define MY_core_file_failing_command _bfd_dummy_core_file_failing_command
+#endif
+#ifndef MY_core_file_failing_signal
+#define MY_core_file_failing_signal _bfd_dummy_core_file_failing_signal
+#endif
+#ifndef MY_core_file_matches_executable_p
+#define MY_core_file_matches_executable_p \
+ _bfd_dummy_core_file_matches_executable_p
+#endif
+#ifndef MY_core_file_p
+#define MY_core_file_p _bfd_dummy_target
+#endif
+
+#ifndef MY_bfd_debug_info_start
+#define MY_bfd_debug_info_start bfd_void
+#endif
+#ifndef MY_bfd_debug_info_end
+#define MY_bfd_debug_info_end bfd_void
+#endif
+#ifndef MY_bfd_debug_info_accumulate
+#define MY_bfd_debug_info_accumulate \
+ (void (*) PARAMS ((bfd*, struct sec *))) bfd_void
+#endif
+
+#ifndef MY_core_file_failing_command
+#define MY_core_file_failing_command NAME(aout,core_file_failing_command)
+#endif
+#ifndef MY_core_file_failing_signal
+#define MY_core_file_failing_signal NAME(aout,core_file_failing_signal)
+#endif
+#ifndef MY_core_file_matches_executable_p
+#define MY_core_file_matches_executable_p NAME(aout,core_file_matches_executable_p)
+#endif
+#ifndef MY_slurp_armap
+#define MY_slurp_armap NAME(aout,slurp_armap)
+#endif
+#ifndef MY_slurp_extended_name_table
+#define MY_slurp_extended_name_table NAME(aout,slurp_extended_name_table)
+#endif
+#ifndef MY_truncate_arname
+#define MY_truncate_arname NAME(aout,truncate_arname)
+#endif
+#ifndef MY_write_armap
+#define MY_write_armap NAME(aout,write_armap)
+#endif
+#ifndef MY_close_and_cleanup
+#define MY_close_and_cleanup NAME(aout,close_and_cleanup)
+#endif
+#ifndef MY_set_section_contents
+#define MY_set_section_contents NAME(aout,set_section_contents)
+#endif
+#ifndef MY_get_section_contents
+#define MY_get_section_contents NAME(aout,get_section_contents)
+#endif
+#ifndef MY_new_section_hook
+#define MY_new_section_hook NAME(aout,new_section_hook)
+#endif
+#ifndef MY_get_symtab_upper_bound
+#define MY_get_symtab_upper_bound NAME(aout,get_symtab_upper_bound)
+#endif
+#ifndef MY_get_symtab
+#define MY_get_symtab NAME(aout,get_symtab)
+#endif
+#ifndef MY_get_reloc_upper_bound
+#define MY_get_reloc_upper_bound NAME(aout,get_reloc_upper_bound)
+#endif
+#ifndef MY_canonicalize_reloc
+#define MY_canonicalize_reloc NAME(aout,canonicalize_reloc)
+#endif
+#ifndef MY_make_empty_symbol
+#define MY_make_empty_symbol NAME(aout,make_empty_symbol)
+#endif
+#ifndef MY_print_symbol
+#define MY_print_symbol NAME(aout,print_symbol)
+#endif
+#ifndef MY_get_symbol_info
+#define MY_get_symbol_info NAME(aout,get_symbol_info)
+#endif
+#ifndef MY_get_lineno
+#define MY_get_lineno NAME(aout,get_lineno)
+#endif
+#ifndef MY_set_arch_mach
+#define MY_set_arch_mach NAME(aout,set_arch_mach)
+#endif
+#ifndef MY_openr_next_archived_file
+#define MY_openr_next_archived_file NAME(aout,openr_next_archived_file)
+#endif
+#ifndef MY_find_nearest_line
+#define MY_find_nearest_line NAME(aout,find_nearest_line)
+#endif
+#ifndef MY_generic_stat_arch_elt
+#define MY_generic_stat_arch_elt NAME(aout,generic_stat_arch_elt)
+#endif
+#ifndef MY_sizeof_headers
+#define MY_sizeof_headers NAME(aout,sizeof_headers)
+#endif
+#ifndef MY_bfd_debug_info_start
+#define MY_bfd_debug_info_start NAME(aout,bfd_debug_info_start)
+#endif
+#ifndef MY_bfd_debug_info_end
+#define MY_bfd_debug_info_end NAME(aout,bfd_debug_info_end)
+#endif
+#ifndef MY_bfd_debug_info_accumulat
+#define MY_bfd_debug_info_accumulat NAME(aout,bfd_debug_info_accumulat)
+#endif
+#ifndef MY_reloc_howto_type_lookup
+#define MY_reloc_howto_type_lookup NAME(aout,reloc_type_lookup)
+#endif
+#ifndef MY_make_debug_symbol
+#define MY_make_debug_symbol 0
+#endif
+
+/* Aout symbols normally have leading underscores */
+#ifndef MY_symbol_leading_char
+#define MY_symbol_leading_char '_'
+#endif
+
+/* Aout archives normally use spaces for padding */
+#ifndef AR_PAD_CHAR
+#define AR_PAD_CHAR ' '
+#endif
+
+#ifndef MY_BFD_TARGET
+bfd_target MY(vec) =
+{
+ TARGETNAME, /* name */
+ bfd_target_aout_flavour,
+#ifdef TARGET_IS_BIG_ENDIAN_P
+ true, /* target byte order (big) */
+ true, /* target headers byte order (big) */
+#else
+ false, /* target byte order (little) */
+ false, /* target headers byte order (little) */
+#endif
+ (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 */
+ MY_symbol_leading_char,
+ AR_PAD_CHAR, /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 3, /* minimum alignment */
+#ifdef TARGET_IS_BIG_ENDIAN_P
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
+#else
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+#endif
+ {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, MY_core_file_p},
+ {bfd_false, MY_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, MY_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ MY_core_file_failing_command,
+ MY_core_file_failing_signal,
+ MY_core_file_matches_executable_p,
+ MY_slurp_armap,
+ MY_slurp_extended_name_table,
+ MY_truncate_arname,
+ MY_write_armap,
+ MY_close_and_cleanup,
+ MY_set_section_contents,
+ MY_get_section_contents,
+ MY_new_section_hook,
+ MY_get_symtab_upper_bound,
+ MY_get_symtab,
+ MY_get_reloc_upper_bound,
+ MY_canonicalize_reloc,
+ MY_make_empty_symbol,
+ MY_print_symbol,
+ MY_get_symbol_info,
+ MY_get_lineno,
+ MY_set_arch_mach,
+ MY_openr_next_archived_file,
+ MY_find_nearest_line,
+ MY_generic_stat_arch_elt,
+ MY_sizeof_headers,
+ MY_bfd_debug_info_start,
+ MY_bfd_debug_info_end,
+ MY_bfd_debug_info_accumulate,
+ bfd_generic_get_relocated_section_contents,
+ bfd_generic_relax_section,
+ bfd_generic_seclet_link,
+ MY_reloc_howto_type_lookup,
+ MY_make_debug_symbol,
+ (PTR) MY_backend_data,
+};
+#endif /* MY_BFD_TARGET */
diff --git a/gnu/usr.bin/gdb/bfd/aout32.c b/gnu/usr.bin/gdb/bfd/aout32.c
new file mode 100644
index 000000000000..84d20872fc96
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/aout32.c
@@ -0,0 +1,23 @@
+/* BFD back-end for 32-bit a.out files.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define ARCH_SIZE 32
+
+#include "aoutx.h"
diff --git a/gnu/usr.bin/gdb/bfd/aoutx.h b/gnu/usr.bin/gdb/bfd/aoutx.h
new file mode 100644
index 000000000000..1ab442926ff2
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/aoutx.h
@@ -0,0 +1,2568 @@
+/* BFD semi-generic back-end for a.out binaries.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ a.out backends
+
+
+DESCRIPTION
+
+ BFD supports a number of different flavours of a.out format,
+ though the major differences are only the sizes of the
+ structures on disk, and the shape of the relocation
+ information.
+
+ The support is split into a basic support file @code{aoutx.h}
+ and other files which derive functions from the base. One
+ derivation file is @code{aoutf1.h} (for a.out flavour 1), and
+ adds to the basic a.out functions support for sun3, sun4, 386
+ and 29k a.out files, to create a target jump vector for a
+ specific target.
+
+ This information is further split out into more specific files
+ for each machine, including @code{sunos.c} for sun3 and sun4,
+ @code{newsos3.c} for the Sony NEWS, and @code{demo64.c} for a
+ demonstration of a 64 bit a.out format.
+
+ The base file @code{aoutx.h} defines general mechanisms for
+ reading and writing records to and from disk, and various
+ other methods which BFD requires. It is included by
+ @code{aout32.c} and @code{aout64.c} to form the names
+ aout_32_swap_exec_header_in, aout_64_swap_exec_header_in, etc.
+
+ As an example, this is what goes on to make the back end for a
+ sun4, from aout32.c
+
+| #define ARCH_SIZE 32
+| #include "aoutx.h"
+
+ Which exports names:
+
+| ...
+| aout_32_canonicalize_reloc
+| aout_32_find_nearest_line
+| aout_32_get_lineno
+| aout_32_get_reloc_upper_bound
+| ...
+
+ from sunos.c
+
+| #define ARCH 32
+| #define TARGET_NAME "a.out-sunos-big"
+| #define VECNAME sunos_big_vec
+| #include "aoutf1.h"
+
+ requires all the names from aout32.c, and produces the jump vector
+
+| sunos_big_vec
+
+ The file host-aout.c is a special case. It is for a large set
+ of hosts that use ``more or less standard'' a.out files, and
+ for which cross-debugging is not interesting. It uses the
+ standard 32-bit a.out support routines, but determines the
+ file offsets and addresses of the text, data, and BSS
+ sections, the machine architecture and machine type, and the
+ entry point address, in a host-dependent manner. Once these
+ values have been determined, generic code is used to handle
+ the object file.
+
+ When porting it to run on a new system, you must supply:
+
+| HOST_PAGE_SIZE
+| HOST_SEGMENT_SIZE
+| HOST_MACHINE_ARCH (optional)
+| HOST_MACHINE_MACHINE (optional)
+| HOST_TEXT_START_ADDR
+| HOST_STACK_END_ADDR
+
+ in the file <<../include/sys/h-XXX.h>> (for your host). These
+ values, plus the structures and macros defined in <<a.out.h>> on
+ your host system, will produce a BFD target that will access
+ ordinary a.out files on your host. To configure a new machine
+ to use <<host-aout.c>., specify:
+
+| TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec
+| TDEPFILES= host-aout.o trad-core.o
+
+ in the <<config/mt-XXX>> file, and modify configure.in to use the
+ <<mt-XXX>> file (by setting "<<bfd_target=XXX>>") when your
+ configuration is selected.
+
+*/
+
+/* Some assumptions:
+ * Any BFD with D_PAGED set is ZMAGIC, and vice versa.
+ Doesn't matter what the setting of WP_TEXT is on output, but it'll
+ get set on input.
+ * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC.
+ * Any BFD with both flags clear is OMAGIC.
+ (Just want to make these explicit, so the conditions tested in this
+ file make sense if you're more familiar with a.out than with BFD.) */
+
+#define KEEPIT flags
+#define KEEPITTYPE int
+
+#include <assert.h>
+#include <string.h> /* For strchr and friends */
+#include "bfd.h"
+#include <sysdep.h>
+#include <ansidecl.h>
+
+struct external_exec;
+#include "libaout.h"
+#include "libbfd.h"
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+
+extern void (*bfd_error_trap)();
+
+/*
+SUBSECTION
+ relocations
+
+DESCRIPTION
+ The file @code{aoutx.h} caters for both the @emph{standard}
+ and @emph{extended} forms of a.out relocation records.
+
+ The standard records are characterised by containing only an
+ address, a symbol index and a type field. The extended records
+ (used on 29ks and sparcs) also have a full integer for an
+ addend.
+
+*/
+#define CTOR_TABLE_RELOC_IDX 2
+
+#define howto_table_ext NAME(aout,ext_howto_table)
+#define howto_table_std NAME(aout,std_howto_table)
+
+reloc_howto_type howto_table_ext[] =
+{
+ /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */
+ HOWTO(RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", false, 0,0x000000ff, false),
+ HOWTO(RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", false, 0,0x0000ffff, false),
+ HOWTO(RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", false, 0,0xffffffff, false),
+ HOWTO(RELOC_DISP8, 0, 0, 8, true, 0, complain_overflow_signed,0,"DISP8", false, 0,0x000000ff, false),
+ HOWTO(RELOC_DISP16, 0, 1, 16, true, 0, complain_overflow_signed,0,"DISP16", false, 0,0x0000ffff, false),
+ HOWTO(RELOC_DISP32, 0, 2, 32, true, 0, complain_overflow_signed,0,"DISP32", false, 0,0xffffffff, false),
+ HOWTO(RELOC_WDISP30,2, 2, 30, true, 0, complain_overflow_signed,0,"WDISP30", false, 0,0x3fffffff, false),
+ HOWTO(RELOC_WDISP22,2, 2, 22, true, 0, complain_overflow_signed,0,"WDISP22", false, 0,0x003fffff, false),
+ HOWTO(RELOC_HI22, 10, 2, 22, false, 0, complain_overflow_bitfield,0,"HI22", false, 0,0x003fffff, false),
+ HOWTO(RELOC_22, 0, 2, 22, false, 0, complain_overflow_bitfield,0,"22", false, 0,0x003fffff, false),
+ HOWTO(RELOC_13, 0, 2, 13, false, 0, complain_overflow_bitfield,0,"13", false, 0,0x00001fff, false),
+ HOWTO(RELOC_LO10, 0, 2, 10, false, 0, complain_overflow_dont,0,"LO10", false, 0,0x000003ff, false),
+ HOWTO(RELOC_SFA_BASE,0, 2, 32, false, 0, complain_overflow_bitfield,0,"SFA_BASE", false, 0,0xffffffff, false),
+ HOWTO(RELOC_SFA_OFF13,0,2, 32, false, 0, complain_overflow_bitfield,0,"SFA_OFF13",false, 0,0xffffffff, false),
+ HOWTO(RELOC_BASE10, 0, 2, 16, false, 0, complain_overflow_bitfield,0,"BASE10", false, 0,0x0000ffff, false),
+ HOWTO(RELOC_BASE13, 0, 2, 13, false, 0, complain_overflow_bitfield,0,"BASE13", false, 0,0x00001fff, false),
+ HOWTO(RELOC_BASE22, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"BASE22", false, 0,0x00000000, false),
+ HOWTO(RELOC_PC10, 0, 2, 10, false, 0, complain_overflow_bitfield,0,"PC10", false, 0,0x000003ff, false),
+ HOWTO(RELOC_PC22, 0, 2, 22, false, 0, complain_overflow_bitfield,0,"PC22", false, 0,0x003fffff, false),
+ HOWTO(RELOC_JMP_TBL,0, 2, 32, false, 0, complain_overflow_bitfield,0,"JMP_TBL", false, 0,0xffffffff, false),
+ HOWTO(RELOC_SEGOFF16,0, 2, 0, false, 0, complain_overflow_bitfield,0,"SEGOFF16", false, 0,0x00000000, false),
+ HOWTO(RELOC_GLOB_DAT,0, 2, 0, false, 0, complain_overflow_bitfield,0,"GLOB_DAT", false, 0,0x00000000, false),
+ HOWTO(RELOC_JMP_SLOT,0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_SLOT", false, 0,0x00000000, false),
+ HOWTO(RELOC_RELATIVE,0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false),
+};
+
+/* Convert standard reloc records to "arelent" format (incl byte swap). */
+
+reloc_howto_type howto_table_std[] = {
+ /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */
+HOWTO( 0, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", true, 0x000000ff,0x000000ff, false),
+HOWTO( 1, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", true, 0x0000ffff,0x0000ffff, false),
+HOWTO( 2, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", true, 0xffffffff,0xffffffff, false),
+HOWTO( 3, 0, 4, 64, false, 0, complain_overflow_bitfield,0,"64", true, 0xdeaddead,0xdeaddead, false),
+HOWTO( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", true, 0x000000ff,0x000000ff, false),
+HOWTO( 5, 0, 1, 16, true, 0, complain_overflow_signed, 0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
+HOWTO( 6, 0, 2, 32, true, 0, complain_overflow_signed, 0,"DISP32", true, 0xffffffff,0xffffffff, false),
+HOWTO( 7, 0, 4, 64, true, 0, complain_overflow_signed, 0,"DISP64", true, 0xfeedface,0xfeedface, false),
+{ -1 },
+HOWTO( 9, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"BASE16", false,0xffffffff,0xffffffff, false),
+HOWTO(10, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"BASE32", false,0xffffffff,0xffffffff, false),
+};
+
+#define TABLE_SIZE(TABLE) (sizeof(TABLE)/sizeof(TABLE[0]))
+
+CONST struct reloc_howto_struct *
+DEFUN(NAME(aout,reloc_type_lookup),(abfd,code),
+ bfd *abfd AND
+ bfd_reloc_code_real_type code)
+{
+#define EXT(i,j) case i: return &howto_table_ext[j]
+#define STD(i,j) case i: return &howto_table_std[j]
+ int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
+ if (code == BFD_RELOC_CTOR)
+ switch (bfd_get_arch_info (abfd)->bits_per_address)
+ {
+ case 32:
+ code = BFD_RELOC_32;
+ break;
+ }
+ if (ext)
+ switch (code)
+ {
+ EXT (BFD_RELOC_32, 2);
+ EXT (BFD_RELOC_HI22, 8);
+ EXT (BFD_RELOC_LO10, 11);
+ EXT (BFD_RELOC_32_PCREL_S2, 6);
+ default: return (CONST struct reloc_howto_struct *) 0;
+ }
+ else
+ /* std relocs */
+ switch (code)
+ {
+ STD (BFD_RELOC_16, 1);
+ STD (BFD_RELOC_32, 2);
+ STD (BFD_RELOC_8_PCREL, 4);
+ STD (BFD_RELOC_16_PCREL, 5);
+ STD (BFD_RELOC_32_PCREL, 6);
+ STD (BFD_RELOC_16_BASEREL, 9);
+ STD (BFD_RELOC_32_BASEREL, 10);
+ default: return (CONST struct reloc_howto_struct *) 0;
+ }
+}
+
+extern bfd_error_vector_type bfd_error_vector;
+
+/*
+SUBSECTION
+ Internal Entry Points
+
+DESCRIPTION
+ @code{aoutx.h} exports several routines for accessing the
+ contents of an a.out file, which are gathered and exported in
+ turn by various format specific files (eg sunos.c).
+
+*/
+
+/*
+FUNCTION
+ aout_<size>_swap_exec_header_in
+
+DESCRIPTION
+ Swaps the information in an executable header taken from a raw
+ byte stream memory image, into the internal exec_header
+ structure.
+
+SYNOPSIS
+ void aout_<size>_swap_exec_header_in,
+ (bfd *abfd,
+ struct external_exec *raw_bytes,
+ struct internal_exec *execp);
+*/
+
+#ifndef NAME_swap_exec_header_in
+void
+DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp),
+ bfd *abfd AND
+ struct external_exec *raw_bytes AND
+ struct internal_exec *execp)
+{
+ struct external_exec *bytes = (struct external_exec *)raw_bytes;
+
+ /* The internal_exec structure has some fields that are unused in this
+ configuration (IE for i960), so ensure that all such uninitialized
+ fields are zero'd out. There are places where two of these structs
+ are memcmp'd, and thus the contents do matter. */
+ memset (execp, 0, sizeof (struct internal_exec));
+ /* Now fill in fields in the execp, from the bytes in the raw data. */
+ execp->a_info = bfd_h_get_32 (abfd, bytes->e_info);
+ execp->a_text = GET_WORD (abfd, bytes->e_text);
+ execp->a_data = GET_WORD (abfd, bytes->e_data);
+ execp->a_bss = GET_WORD (abfd, bytes->e_bss);
+ execp->a_syms = GET_WORD (abfd, bytes->e_syms);
+ execp->a_entry = GET_WORD (abfd, bytes->e_entry);
+ execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
+ execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
+}
+#define NAME_swap_exec_header_in NAME(aout,swap_exec_header_in)
+#endif
+
+/*
+FUNCTION
+ aout_<size>_swap_exec_header_out
+
+DESCRIPTION
+ Swaps the information in an internal exec header structure
+ into the supplied buffer ready for writing to disk.
+
+SYNOPSIS
+ void aout_<size>_swap_exec_header_out
+ (bfd *abfd,
+ struct internal_exec *execp,
+ struct external_exec *raw_bytes);
+*/
+void
+DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes),
+ bfd *abfd AND
+ struct internal_exec *execp AND
+ struct external_exec *raw_bytes)
+{
+ struct external_exec *bytes = (struct external_exec *)raw_bytes;
+
+ /* Now fill in fields in the raw data, from the fields in the exec struct. */
+ bfd_h_put_32 (abfd, execp->a_info , bytes->e_info);
+ PUT_WORD (abfd, execp->a_text , bytes->e_text);
+ PUT_WORD (abfd, execp->a_data , bytes->e_data);
+ PUT_WORD (abfd, execp->a_bss , bytes->e_bss);
+ PUT_WORD (abfd, execp->a_syms , bytes->e_syms);
+ PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
+ PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
+ PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
+}
+
+
+
+/*
+FUNCTION
+ aout_<size>_some_aout_object_p
+
+DESCRIPTION
+ Some A.OUT variant thinks that the file whose format we're
+ checking is an a.out file. Do some more checking, and set up
+ for access if it really is. Call back to the calling
+ environments "finish up" function just before returning, to
+ handle any last-minute setup.
+
+SYNOPSIS
+ bfd_target *aout_<size>_some_aout_object_p
+ (bfd *abfd,
+ bfd_target *(*callback_to_real_object_p)());
+*/
+
+bfd_target *
+DEFUN(NAME(aout,some_aout_object_p),(abfd, execp, callback_to_real_object_p),
+ bfd *abfd AND
+ struct internal_exec *execp AND
+ bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *)))
+{
+ struct aout_data_struct *rawptr, *oldrawptr;
+ bfd_target *result;
+
+ rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, sizeof (struct aout_data_struct ));
+ if (rawptr == NULL) {
+ bfd_error = no_memory;
+ return 0;
+ }
+
+ oldrawptr = abfd->tdata.aout_data;
+ abfd->tdata.aout_data = rawptr;
+
+ /* Copy the contents of the old tdata struct.
+ In particular, we want the subformat, since for hpux it was set in
+ hp300hpux.c:swap_exec_header_in and will be used in
+ hp300hpux.c:callback. */
+ if (oldrawptr != NULL)
+ *abfd->tdata.aout_data = *oldrawptr;
+
+ abfd->tdata.aout_data->a.hdr = &rawptr->e;
+ *(abfd->tdata.aout_data->a.hdr) = *execp; /* Copy in the internal_exec struct */
+ execp = abfd->tdata.aout_data->a.hdr;
+
+ /* Set the file flags */
+ abfd->flags = NO_FLAGS;
+ if (execp->a_drsize || execp->a_trsize)
+ abfd->flags |= HAS_RELOC;
+ /* Setting of EXEC_P has been deferred to the bottom of this function */
+ if (execp->a_syms)
+ abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+
+ if (N_MAGIC (*execp) == ZMAGIC)
+ {
+ abfd->flags |= D_PAGED|WP_TEXT;
+ adata(abfd).magic = z_magic;
+ }
+ else if (N_MAGIC (*execp) == NMAGIC)
+ {
+ abfd->flags |= WP_TEXT;
+ adata(abfd).magic = n_magic;
+ }
+ else
+ adata(abfd).magic = o_magic;
+
+ bfd_get_start_address (abfd) = execp->a_entry;
+
+ obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+ bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
+
+ /* The default relocation entry size is that of traditional V7 Unix. */
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+
+ /* The default symbol entry size is that of traditional Unix. */
+ obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
+
+ /* Create the sections. This is raunchy, but bfd_close wants to reclaim
+ them. */
+
+ obj_textsec (abfd) = bfd_make_section_old_way (abfd, ".text");
+ obj_datasec (abfd) = bfd_make_section_old_way (abfd, ".data");
+ obj_bsssec (abfd) = bfd_make_section_old_way (abfd, ".bss");
+
+#if 0
+ (void)bfd_make_section (abfd, ".text");
+ (void)bfd_make_section (abfd, ".data");
+ (void)bfd_make_section (abfd, ".bss");
+#endif
+
+ obj_datasec (abfd)->_raw_size = execp->a_data;
+ obj_bsssec (abfd)->_raw_size = execp->a_bss;
+
+ obj_textsec (abfd)->flags = (execp->a_trsize != 0 ?
+ (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC) :
+ (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
+ obj_datasec (abfd)->flags = (execp->a_drsize != 0 ?
+ (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC) :
+ (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
+ obj_bsssec (abfd)->flags = SEC_ALLOC;
+
+#ifdef THIS_IS_ONLY_DOCUMENTATION
+ /* The common code can't fill in these things because they depend
+ on either the start address of the text segment, the rounding
+ up of virtual addersses between segments, or the starting file
+ position of the text segment -- all of which varies among different
+ versions of a.out. */
+
+ /* Call back to the format-dependent code to fill in the rest of the
+ fields and do any further cleanup. Things that should be filled
+ in by the callback: */
+
+ struct exec *execp = exec_hdr (abfd);
+
+ obj_textsec (abfd)->size = N_TXTSIZE(*execp);
+ obj_textsec (abfd)->raw_size = N_TXTSIZE(*execp);
+ /* data and bss are already filled in since they're so standard */
+
+ /* The virtual memory addresses of the sections */
+ obj_textsec (abfd)->vma = N_TXTADDR(*execp);
+ obj_datasec (abfd)->vma = N_DATADDR(*execp);
+ obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
+
+ /* The file offsets of the sections */
+ obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
+ obj_datasec (abfd)->filepos = N_DATOFF(*execp);
+
+ /* The file offsets of the relocation info */
+ obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
+ obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
+
+ /* The file offsets of the string table and symbol table. */
+ obj_str_filepos (abfd) = N_STROFF (*execp);
+ obj_sym_filepos (abfd) = N_SYMOFF (*execp);
+
+ /* Determine the architecture and machine type of the object file. */
+ switch (N_MACHTYPE (*exec_hdr (abfd))) {
+ default:
+ abfd->obj_arch = bfd_arch_obscure;
+ break;
+ }
+
+ adata(abfd)->page_size = PAGE_SIZE;
+ adata(abfd)->segment_size = SEGMENT_SIZE;
+ adata(abfd)->exec_bytes_size = EXEC_BYTES_SIZE;
+
+ return abfd->xvec;
+
+ /* The architecture is encoded in various ways in various a.out variants,
+ or is not encoded at all in some of them. The relocation size depends
+ on the architecture and the a.out variant. Finally, the return value
+ is the bfd_target vector in use. If an error occurs, return zero and
+ set bfd_error to the appropriate error code.
+
+ Formats such as b.out, which have additional fields in the a.out
+ header, should cope with them in this callback as well. */
+#endif /* DOCUMENTATION */
+
+ result = (*callback_to_real_object_p)(abfd);
+
+ /* Now that the segment addresses have been worked out, take a better
+ guess at whether the file is executable. If the entry point
+ is within the text segment, assume it is. (This makes files
+ executable even if their entry point address is 0, as long as
+ their text starts at zero.)
+
+ At some point we should probably break down and stat the file and
+ declare it executable if (one of) its 'x' bits are on... */
+ if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
+ (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size))
+ abfd->flags |= EXEC_P;
+ if (result)
+ {
+#if 0 /* These should be set correctly anyways. */
+ abfd->sections = obj_textsec (abfd);
+ obj_textsec (abfd)->next = obj_datasec (abfd);
+ obj_datasec (abfd)->next = obj_bsssec (abfd);
+#endif
+ }
+ else
+ {
+ free (rawptr);
+ abfd->tdata.aout_data = oldrawptr;
+ }
+ return result;
+}
+
+/*
+FUNCTION
+ aout_<size>_mkobject
+
+DESCRIPTION
+ This routine initializes a BFD for use with a.out files.
+
+SYNOPSIS
+ boolean aout_<size>_mkobject, (bfd *);
+*/
+
+boolean
+DEFUN(NAME(aout,mkobject),(abfd),
+ bfd *abfd)
+{
+ struct aout_data_struct *rawptr;
+
+ bfd_error = system_call_error;
+
+ /* Use an intermediate variable for clarity */
+ rawptr = (struct aout_data_struct *)bfd_zalloc (abfd, sizeof (struct aout_data_struct ));
+
+ if (rawptr == NULL) {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ abfd->tdata.aout_data = rawptr;
+ exec_hdr (abfd) = &(rawptr->e);
+
+ /* 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");
+ bfd_make_section (abfd, BFD_ABS_SECTION_NAME);
+ bfd_make_section (abfd, BFD_UND_SECTION_NAME);
+ bfd_make_section (abfd, BFD_COM_SECTION_NAME);
+
+ return true;
+}
+
+
+/*
+FUNCTION
+ aout_<size>_machine_type
+
+DESCRIPTION
+ 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.
+
+SYNOPSIS
+ enum machine_type aout_<size>_machine_type
+ (enum bfd_architecture arch,
+ unsigned long machine));
+*/
+
+enum machine_type
+DEFUN(NAME(aout,machine_type),(arch, machine),
+ enum bfd_architecture arch AND
+ 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_68010; 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;
+
+ case bfd_arch_mips:
+ switch (machine) {
+ case 0:
+ case 2000:
+ case 3000: arch_flags = M_MIPS1; break;
+ case 4000:
+ case 4400:
+ case 6000: arch_flags = M_MIPS2; break;
+ default: arch_flags = M_UNKNOWN; break;
+ }
+ break;
+
+ default:
+ arch_flags = M_UNKNOWN;
+ }
+ return arch_flags;
+}
+
+
+/*
+FUNCTION
+ aout_<size>_set_arch_mach
+
+DESCRIPTION
+ Sets the architecture and the machine of the BFD to those
+ values supplied. Verifies that the format can support the
+ architecture required.
+
+SYNOPSIS
+ boolean aout_<size>_set_arch_mach,
+ (bfd *,
+ enum bfd_architecture,
+ unsigned long machine));
+*/
+
+boolean
+DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine),
+ bfd *abfd AND
+ enum bfd_architecture arch AND
+ unsigned long machine)
+{
+ if (! bfd_default_set_arch_mach (abfd, arch, machine))
+ return false;
+
+ if (arch != bfd_arch_unknown &&
+ NAME(aout,machine_type) (arch, machine) == M_UNKNOWN)
+ return false; /* We can't represent this type */
+
+ /* Determine the size of a relocation entry */
+ switch (arch) {
+ case bfd_arch_sparc:
+ case bfd_arch_a29k:
+ case bfd_arch_mips:
+ obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
+ break;
+ default:
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+ break;
+ }
+
+ return (*aout_backend_info(abfd)->set_sizes) (abfd);
+}
+
+boolean
+DEFUN (NAME (aout,adjust_sizes_and_vmas), (abfd, text_size, text_end),
+ bfd *abfd AND bfd_size_type *text_size AND file_ptr *text_end)
+{
+ struct internal_exec *execp = exec_hdr (abfd);
+ if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL))
+ {
+ bfd_error = invalid_operation;
+ return false;
+ }
+ if (adata(abfd).magic != undecided_magic) return true;
+ obj_textsec(abfd)->_raw_size =
+ align_power(obj_textsec(abfd)->_raw_size,
+ obj_textsec(abfd)->alignment_power);
+
+ *text_size = obj_textsec (abfd)->_raw_size;
+ /* Rule (heuristic) for when to pad to a new page. Note that there
+ * are (at least) two ways demand-paged (ZMAGIC) files have been
+ * handled. Most Berkeley-based systems start the text segment at
+ * (PAGE_SIZE). However, newer versions of SUNOS start the text
+ * segment right after the exec header; the latter is counted in the
+ * text segment size, and is paged in by the kernel with the rest of
+ * the text. */
+
+ /* This perhaps isn't the right way to do this, but made it simpler for me
+ to understand enough to implement it. Better would probably be to go
+ right from BFD flags to alignment/positioning characteristics. But the
+ old code was sloppy enough about handling the flags, and had enough
+ other magic, that it was a little hard for me to understand. I think
+ I understand it better now, but I haven't time to do the cleanup this
+ minute. */
+ if (adata(abfd).magic == undecided_magic)
+ {
+ if (abfd->flags & D_PAGED)
+ /* Whether or not WP_TEXT is set -- let D_PAGED override. */
+ /* @@ What about QMAGIC? */
+ adata(abfd).magic = z_magic;
+ else if (abfd->flags & WP_TEXT)
+ adata(abfd).magic = n_magic;
+ else
+ adata(abfd).magic = o_magic;
+ }
+
+#ifdef BFD_AOUT_DEBUG /* requires gcc2 */
+#if __GNUC__ >= 2
+ fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n",
+ ({ char *str;
+ switch (adata(abfd).magic) {
+ case n_magic: str = "NMAGIC"; break;
+ case o_magic: str = "OMAGIC"; break;
+ case z_magic: str = "ZMAGIC"; break;
+ default: abort ();
+ }
+ str;
+ }),
+ obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->alignment_power,
+ obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->alignment_power,
+ obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size, obj_bsssec(abfd)->alignment_power);
+#endif
+#endif
+
+ switch (adata(abfd).magic)
+ {
+ case o_magic:
+ {
+ file_ptr pos = adata (abfd).exec_bytes_size;
+ bfd_vma vma = 0;
+ int pad = 0;
+
+ obj_textsec(abfd)->filepos = pos;
+ pos += obj_textsec(abfd)->_raw_size;
+ vma += obj_textsec(abfd)->_raw_size;
+ if (!obj_datasec(abfd)->user_set_vma)
+ {
+#if 0 /* ?? Does alignment in the file image really matter? */
+ pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma;
+#endif
+ obj_textsec(abfd)->_raw_size += pad;
+ pos += pad;
+ vma += pad;
+ obj_datasec(abfd)->vma = vma;
+ }
+ obj_datasec(abfd)->filepos = pos;
+ pos += obj_datasec(abfd)->_raw_size;
+ vma += obj_datasec(abfd)->_raw_size;
+ if (!obj_bsssec(abfd)->user_set_vma)
+ {
+#if 0
+ pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma;
+#endif
+ obj_datasec(abfd)->_raw_size += pad;
+ pos += pad;
+ vma += pad;
+ obj_bsssec(abfd)->vma = vma;
+ }
+ obj_bsssec(abfd)->filepos = pos;
+ execp->a_text = obj_textsec(abfd)->_raw_size;
+ execp->a_data = obj_datasec(abfd)->_raw_size;
+ execp->a_bss = obj_bsssec(abfd)->_raw_size;
+ N_SET_MAGIC (*execp, OMAGIC);
+ }
+ break;
+ case z_magic:
+ {
+ bfd_size_type data_pad, text_pad;
+ file_ptr text_end;
+ CONST struct aout_backend_data *abdp;
+ int ztih;
+ bfd_vma data_vma;
+
+ abdp = aout_backend_info (abfd);
+ ztih = abdp && abdp->text_includes_header;
+ obj_textsec(abfd)->filepos = (ztih
+ ? adata(abfd).exec_bytes_size
+ : adata(abfd).page_size);
+ if (! obj_textsec(abfd)->user_set_vma)
+ /* ?? Do we really need to check for relocs here? */
+ obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC)
+ ? 0
+ : (ztih
+ ? (abdp->default_text_vma
+ + adata(abfd).exec_bytes_size)
+ : abdp->default_text_vma));
+ /* Could take strange alignment of text section into account here? */
+
+ /* Find start of data. */
+ text_end = obj_textsec(abfd)->filepos + obj_textsec(abfd)->_raw_size;
+ text_pad = BFD_ALIGN (text_end, adata(abfd).page_size) - text_end;
+ obj_textsec(abfd)->_raw_size += text_pad;
+ text_end += text_pad;
+
+ if (!obj_datasec(abfd)->user_set_vma)
+ {
+ bfd_vma vma;
+ vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size;
+ obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size);
+ }
+ data_vma = obj_datasec(abfd)->vma;
+ if (abdp && abdp->zmagic_mapped_contiguous)
+ {
+ text_pad = (obj_datasec(abfd)->vma
+ - obj_textsec(abfd)->vma
+ - obj_textsec(abfd)->_raw_size);
+ obj_textsec(abfd)->_raw_size += text_pad;
+ }
+ obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos
+ + obj_textsec(abfd)->_raw_size);
+
+ /* Fix up exec header while we're at it. */
+ execp->a_text = obj_textsec(abfd)->_raw_size;
+ if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted)))
+ execp->a_text += adata(abfd).exec_bytes_size;
+ N_SET_MAGIC (*execp, ZMAGIC);
+ /* Spec says data section should be rounded up to page boundary. */
+ /* If extra space in page is left after data section, fudge data
+ in the header so that the bss section looks smaller by that
+ amount. We'll start the bss section there, and lie to the OS. */
+ obj_datasec(abfd)->_raw_size
+ = align_power (obj_datasec(abfd)->_raw_size,
+ obj_bsssec(abfd)->alignment_power);
+ execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size,
+ adata(abfd).page_size);
+ data_pad = execp->a_data - obj_datasec(abfd)->_raw_size;
+
+ if (!obj_bsssec(abfd)->user_set_vma)
+ obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma
+ + obj_datasec(abfd)->_raw_size);
+ if (data_pad > obj_bsssec(abfd)->_raw_size)
+ execp->a_bss = 0;
+ else
+ execp->a_bss = obj_bsssec(abfd)->_raw_size - data_pad;
+ }
+ break;
+ case n_magic:
+ {
+ file_ptr pos = adata(abfd).exec_bytes_size;
+ bfd_vma vma = 0;
+ int pad;
+
+ obj_textsec(abfd)->filepos = pos;
+ if (!obj_textsec(abfd)->user_set_vma)
+ obj_textsec(abfd)->vma = vma;
+ else
+ vma = obj_textsec(abfd)->vma;
+ pos += obj_textsec(abfd)->_raw_size;
+ vma += obj_textsec(abfd)->_raw_size;
+ obj_datasec(abfd)->filepos = pos;
+ if (!obj_datasec(abfd)->user_set_vma)
+ obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size);
+ vma = obj_datasec(abfd)->vma;
+
+ /* Since BSS follows data immediately, see if it needs alignment. */
+ vma += obj_datasec(abfd)->_raw_size;
+ pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma;
+ obj_datasec(abfd)->_raw_size += pad;
+ pos += obj_datasec(abfd)->_raw_size;
+
+ if (!obj_bsssec(abfd)->user_set_vma)
+ obj_bsssec(abfd)->vma = vma;
+ else
+ vma = obj_bsssec(abfd)->vma;
+ }
+ execp->a_text = obj_textsec(abfd)->_raw_size;
+ execp->a_data = obj_datasec(abfd)->_raw_size;
+ execp->a_bss = obj_bsssec(abfd)->_raw_size;
+ N_SET_MAGIC (*execp, NMAGIC);
+ break;
+ default:
+ abort ();
+ }
+#ifdef BFD_AOUT_DEBUG
+ fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n",
+ obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size, obj_textsec(abfd)->filepos,
+ obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size, obj_datasec(abfd)->filepos,
+ obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size);
+#endif
+ return true;
+}
+
+/*
+FUNCTION
+ aout_<size>_new_section_hook
+
+DESCRIPTION
+ Called by the BFD in response to a @code{bfd_make_section}
+ request.
+
+SYNOPSIS
+ boolean aout_<size>_new_section_hook,
+ (bfd *abfd,
+ asection *newsect));
+*/
+boolean
+DEFUN(NAME(aout,new_section_hook),(abfd, newsect),
+ bfd *abfd AND
+ asection *newsect)
+{
+ /* align to double at least */
+ newsect->alignment_power = bfd_get_arch_info(abfd)->section_align_power;
+
+
+ if (bfd_get_format (abfd) == bfd_object)
+ {
+ if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
+ obj_textsec(abfd)= newsect;
+ newsect->target_index = N_TEXT | N_EXT;
+ return true;
+ }
+
+ if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
+ obj_datasec(abfd) = newsect;
+ newsect->target_index = N_DATA | N_EXT;
+ return true;
+ }
+
+ if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
+ obj_bsssec(abfd) = newsect;
+ newsect->target_index = N_BSS | N_EXT;
+ return true;
+ }
+
+ }
+
+ /* We allow more than three sections internally */
+ return true;
+}
+
+boolean
+DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count),
+ bfd *abfd AND
+ sec_ptr section AND
+ PTR location AND
+ file_ptr offset AND
+ bfd_size_type count)
+{
+ file_ptr text_end;
+ bfd_size_type text_size;
+
+ if (abfd->output_has_begun == false)
+ {
+ if (NAME(aout,adjust_sizes_and_vmas) (abfd,
+ &text_size,
+ &text_end) == false)
+ return false;
+ }
+
+ /* regardless, once we know what we're doing, we might as well get going */
+ if (section != obj_bsssec(abfd))
+ {
+ bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+ if (count) {
+ return (bfd_write ((PTR)location, 1, count, abfd) == count) ?
+ true : false;
+ }
+ return true;
+ }
+ return true;
+}
+
+/* Classify stabs symbols */
+
+#define sym_in_text_section(sym) \
+ (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
+
+#define sym_in_data_section(sym) \
+ (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
+
+#define sym_in_bss_section(sym) \
+ (((sym)->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)->type == (N_UNDF | N_EXT) && (sym)->symbol.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)->type & N_EXT) && (sym)->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)->type & ~(N_EXT | N_TYPE)) || (sym)->type == N_FN)
+
+#define sym_is_fortrancommon(sym) \
+ (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
+
+/* Symbol is absolute if it has N_ABS set */
+#define sym_is_absolute(sym) \
+ (((sym)->type & N_TYPE)== N_ABS)
+
+
+#define sym_is_indirect(sym) \
+ (((sym)->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
+DEFUN (translate_from_native_sym_flags, (sym_pointer, cache_ptr, abfd),
+ struct external_nlist *sym_pointer AND
+ aout_symbol_type * cache_ptr AND
+ bfd * abfd)
+{
+ cache_ptr->symbol.section = 0;
+ switch (cache_ptr->type & N_TYPE)
+ {
+ case N_SETA:
+ case N_SETT:
+ case N_SETD:
+ case N_SETB:
+ {
+ char *copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1);
+ asection *section;
+ asection *into_section;
+
+ arelent_chain *reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
+ strcpy (copy, cache_ptr->symbol.name);
+
+ /* Make sure that this bfd has a section with the right contructor
+ name */
+ section = bfd_get_section_by_name (abfd, copy);
+ if (!section)
+ section = bfd_make_section (abfd, copy);
+
+ /* Build a relocation entry for the constructor */
+ switch ((cache_ptr->type & N_TYPE))
+ {
+ case N_SETA:
+ into_section = &bfd_abs_section;
+ cache_ptr->type = N_ABS;
+ break;
+ case N_SETT:
+ into_section = (asection *) obj_textsec (abfd);
+ cache_ptr->type = N_TEXT;
+ break;
+ case N_SETD:
+ into_section = (asection *) obj_datasec (abfd);
+ cache_ptr->type = N_DATA;
+ break;
+ case N_SETB:
+ into_section = (asection *) obj_bsssec (abfd);
+ cache_ptr->type = N_BSS;
+ break;
+ default:
+ abort ();
+ }
+
+ /* Build a relocation pointing into the constuctor section
+ pointing at the symbol in the set vector specified */
+
+ reloc->relent.addend = cache_ptr->symbol.value;
+ cache_ptr->symbol.section = into_section->symbol->section;
+ reloc->relent.sym_ptr_ptr = into_section->symbol_ptr_ptr;
+
+
+ /* 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->next = section->constructor_chain;
+ section->constructor_chain = reloc;
+ reloc->relent.address = section->_raw_size;
+ section->_raw_size += sizeof (int *);
+
+ reloc->relent.howto
+ = (obj_reloc_entry_size(abfd) == RELOC_EXT_SIZE
+ ? howto_table_ext : howto_table_std)
+ + CTOR_TABLE_RELOC_IDX;
+ cache_ptr->symbol.flags |= BSF_CONSTRUCTOR;
+ }
+ break;
+ default:
+ if (cache_ptr->type == N_WARNING)
+ {
+ /* This symbol is the text of a warning message, the next symbol
+ is the symbol to associate the warning with */
+ cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
+
+ /* @@ Stuffing pointers into integers is a no-no.
+ We can usually get away with it if the integer is
+ large enough though. */
+ if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
+ abort ();
+ cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1));
+
+ /* We furgle with the next symbol in place.
+ We don't want it to be undefined, we'll trample the type */
+ (sym_pointer + 1)->e_type[0] = 0xff;
+ break;
+ }
+ if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT))
+ {
+ /* Two symbols in a row for an INDR message. The first symbol
+ contains the name we will match, the second symbol contains
+ the name the first name is translated into. It is supplied to
+ us undefined. This is good, since we want to pull in any files
+ which define it */
+ cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT;
+
+ /* @@ Stuffing pointers into integers is a no-no.
+ We can usually get away with it if the integer is
+ large enough though. */
+ if (sizeof (cache_ptr + 1) > sizeof (bfd_vma))
+ abort ();
+
+ cache_ptr->symbol.value = (bfd_vma) ((cache_ptr + 1));
+ cache_ptr->symbol.section = &bfd_ind_section;
+ }
+
+ else if (sym_is_debugger_info (cache_ptr))
+ {
+ cache_ptr->symbol.flags = BSF_DEBUGGING;
+ /* Work out the section correct for this symbol */
+ switch (cache_ptr->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;
+ default:
+ case N_ABS:
+
+ cache_ptr->symbol.section = &bfd_abs_section;
+ break;
+ }
+ }
+ else
+ {
+
+ if (sym_is_fortrancommon (cache_ptr))
+ {
+ cache_ptr->symbol.flags = 0;
+ cache_ptr->symbol.section = &bfd_com_section;
+ }
+ else
+ {
+
+
+ }
+
+ /* 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 (cache_ptr))
+ {
+ cache_ptr->symbol.value -= obj_textsec (abfd)->vma;
+ cache_ptr->symbol.section = obj_textsec (abfd);
+ }
+ else if (sym_in_data_section (cache_ptr))
+ {
+ cache_ptr->symbol.value -= obj_datasec (abfd)->vma;
+ cache_ptr->symbol.section = obj_datasec (abfd);
+ }
+ else if (sym_in_bss_section (cache_ptr))
+ {
+ cache_ptr->symbol.section = obj_bsssec (abfd);
+ cache_ptr->symbol.value -= obj_bsssec (abfd)->vma;
+ }
+ else if (sym_is_undefined (cache_ptr))
+ {
+ cache_ptr->symbol.flags = 0;
+ cache_ptr->symbol.section = &bfd_und_section;
+ }
+ else if (sym_is_absolute (cache_ptr))
+ {
+ cache_ptr->symbol.section = &bfd_abs_section;
+ }
+
+ if (sym_is_global_defn (cache_ptr))
+ {
+ cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
+ }
+ else
+ {
+ cache_ptr->symbol.flags = BSF_LOCAL;
+ }
+ }
+ }
+ if (cache_ptr->symbol.section == 0)
+ abort ();
+}
+
+
+
+static void
+DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
+ struct external_nlist *sym_pointer AND
+ asymbol *cache_ptr AND
+ bfd *abfd)
+{
+ bfd_vma value = cache_ptr->value;
+
+ /* mask out any existing type bits in case copying from one section
+ to another */
+ sym_pointer->e_type[0] &= ~N_TYPE;
+
+
+ /* We attempt to order these tests by decreasing frequency of success,
+ according to tcov when linking the linker. */
+ if (bfd_get_output_section(cache_ptr) == &bfd_abs_section) {
+ sym_pointer->e_type[0] |= N_ABS;
+ }
+ else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
+ sym_pointer->e_type[0] |= N_TEXT;
+ }
+ else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
+ sym_pointer->e_type[0] |= N_DATA;
+ }
+ else if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
+ sym_pointer->e_type[0] |= N_BSS;
+ }
+ else if (bfd_get_output_section(cache_ptr) == &bfd_und_section)
+ {
+ sym_pointer->e_type[0] = (N_UNDF | N_EXT);
+ }
+ else if (bfd_get_output_section(cache_ptr) == &bfd_ind_section)
+ {
+ sym_pointer->e_type[0] = N_INDR;
+ }
+ else if (bfd_is_com_section (bfd_get_output_section (cache_ptr))) {
+ sym_pointer->e_type[0] = (N_UNDF | N_EXT);
+ }
+ else {
+ if (cache_ptr->section->output_section)
+ {
+
+ bfd_error_vector.nonrepresentable_section(abfd,
+ bfd_get_output_section(cache_ptr)->name);
+ }
+ else
+ {
+ bfd_error_vector.nonrepresentable_section(abfd,
+ cache_ptr->section->name);
+
+ }
+
+ }
+ /* Turn the symbol from section relative to absolute again */
+
+ value += cache_ptr->section->output_section->vma + cache_ptr->section->output_offset ;
+
+
+ if (cache_ptr->flags & (BSF_WARNING)) {
+ (sym_pointer+1)->e_type[0] = 1;
+ }
+
+ if (cache_ptr->flags & BSF_DEBUGGING) {
+ sym_pointer->e_type[0] = ((aout_symbol_type *)cache_ptr)->type;
+ }
+ else if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
+ sym_pointer->e_type[0] |= N_EXT;
+ }
+ if (cache_ptr->flags & BSF_CONSTRUCTOR) {
+ int type = ((aout_symbol_type *)cache_ptr)->type;
+ switch (type)
+ {
+ case N_ABS: type = N_SETA; break;
+ case N_TEXT: type = N_SETT; break;
+ case N_DATA: type = N_SETD; break;
+ case N_BSS: type = N_SETB; break;
+ }
+ sym_pointer->e_type[0] = type;
+ }
+
+ PUT_WORD(abfd, value, sym_pointer->e_value);
+}
+
+/* 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 *
+DEFUN(NAME(aout,make_empty_symbol),(abfd),
+ bfd *abfd)
+{
+ aout_symbol_type *new =
+ (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
+ new->symbol.the_bfd = abfd;
+
+ return &new->symbol;
+}
+
+boolean
+DEFUN(NAME(aout,slurp_symbol_table),(abfd),
+ bfd *abfd)
+{
+ bfd_size_type symbol_size;
+ bfd_size_type string_size;
+ unsigned char string_chars[BYTES_IN_WORD];
+ struct external_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 ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD)
+ return false;
+ string_size = GET_WORD (abfd, string_chars);
+
+ strings =(char *) bfd_alloc(abfd, string_size + 1);
+ cached = (aout_symbol_type *)
+ bfd_zalloc(abfd, (bfd_size_type)(bfd_get_symcount (abfd) * sizeof(aout_symbol_type)));
+
+ /* malloc this, so we can free it if simply. The symbol caching
+ might want to allocate onto the bfd's obstack */
+ syms = (struct external_nlist *) bfd_xmalloc(symbol_size);
+ bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
+ if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size)
+ {
+ bailout:
+ if (syms)
+ free (syms);
+ if (cached)
+ bfd_release (abfd, cached);
+ if (strings)
+ bfd_release (abfd, strings);
+ return false;
+ }
+
+ bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+ if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size)
+ {
+ goto bailout;
+ }
+ strings[string_size] = 0; /* Just in case. */
+
+ /* OK, now walk the new symtable, cacheing symbol properties */
+ {
+ register struct external_nlist *sym_pointer;
+ register struct external_nlist *sym_end = syms + bfd_get_symcount (abfd);
+ register aout_symbol_type *cache_ptr = cached;
+
+ /* Run through table and copy values */
+ for (sym_pointer = syms, cache_ptr = cached;
+ sym_pointer < sym_end; sym_pointer ++, cache_ptr++)
+ {
+ long x = GET_WORD(abfd, sym_pointer->e_strx);
+ cache_ptr->symbol.the_bfd = abfd;
+ if (x == 0)
+ cache_ptr->symbol.name = "";
+ else if (x >= 0 && x < string_size)
+ cache_ptr->symbol.name = x + strings;
+ else
+ goto bailout;
+
+ cache_ptr->symbol.value = GET_SWORD(abfd, sym_pointer->e_value);
+ cache_ptr->desc = bfd_h_get_16(abfd, sym_pointer->e_desc);
+ cache_ptr->other = bfd_h_get_8(abfd, sym_pointer->e_other);
+ cache_ptr->type = bfd_h_get_8(abfd, sym_pointer->e_type);
+ cache_ptr->symbol.udata = 0;
+ translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
+ }
+ }
+
+ obj_aout_symbols (abfd) = cached;
+ free((PTR)syms);
+
+ return true;
+}
+
+
+/* Possible improvements:
+ + look for strings matching trailing substrings of other strings
+ + better data structures? balanced trees?
+ + smaller per-string or per-symbol data? re-use some of the symbol's
+ data fields?
+ + also look at reducing memory use elsewhere -- maybe if we didn't have to
+ construct the entire symbol table at once, we could get by with smaller
+ amounts of VM? (What effect does that have on the string table
+ reductions?)
+ + rip this out of here, put it into its own file in bfd or libiberty, so
+ coff and elf can use it too. I'll work on this soon, but have more
+ pressing tasks right now.
+
+ A hash table might(?) be more efficient for handling exactly the cases that
+ are handled now, but for trailing substring matches, I think we want to
+ examine the `nearest' values (reverse-)lexically, not merely impose a strict
+ order, nor look only for exact-match or not-match. I don't think a hash
+ table would be very useful for that, and I don't feel like fleshing out two
+ completely different implementations. [raeburn:930419.0331EDT] */
+
+struct stringtab_entry {
+ /* Hash value for this string. Only useful so long as we aren't doing
+ substring matches. */
+ unsigned int hash;
+
+ /* Next node to look at, depending on whether the hash value of the string
+ being searched for is less than or greater than the hash value of the
+ current node. For now, `equal to' is lumped in with `greater than', for
+ space efficiency. It's not a common enough case to warrant another field
+ to be used for all nodes. */
+ struct stringtab_entry *less;
+ struct stringtab_entry *greater;
+
+ /* The string itself. */
+ CONST char *string;
+
+ /* The index allocated for this string. */
+ bfd_size_type index;
+
+#ifdef GATHER_STATISTICS
+ /* How many references have there been to this string? (Not currently used;
+ could be dumped out for anaylsis, if anyone's interested.) */
+ unsigned long count;
+#endif
+
+ /* Next node in linked list, in suggested output order. */
+ struct stringtab_entry *next_to_output;
+};
+
+struct stringtab_data {
+ /* Tree of string table entries. */
+ struct stringtab_entry *strings;
+
+ /* Fudge factor used to center top node of tree. */
+ int hash_zero;
+
+ /* Next index value to issue. */
+ bfd_size_type index;
+
+ /* Index used for empty strings. Cached here because checking for them
+ is really easy, and we can avoid searching the tree. */
+ bfd_size_type empty_string_index;
+
+ /* These fields indicate the two ends of a singly-linked list that indicates
+ the order strings should be written out in. Use this order, and no
+ seeking will need to be done, so output efficiency should be maximized. */
+ struct stringtab_entry **end;
+ struct stringtab_entry *output_order;
+
+#ifdef GATHER_STATISTICS
+ /* Number of strings which duplicate strings already in the table. */
+ unsigned long duplicates;
+
+ /* Number of bytes saved by not having to write all the duplicate strings. */
+ unsigned long bytes_saved;
+
+ /* Number of zero-length strings. Currently, these all turn into
+ references to the null byte at the end of the first string. In some
+ cases (possibly not all? explore this...), it should be possible to
+ simply write out a zero index value. */
+ unsigned long empty_strings;
+
+ /* Number of times the hash values matched but the strings were different.
+ Note that this includes the number of times the other string(s) occurs, so
+ there may only be two strings hashing to the same value, even if this
+ number is very large. */
+ unsigned long bad_hash_matches;
+
+ /* Null strings aren't counted in this one.
+ This will probably only be nonzero if we've got an input file
+ which was produced by `ld -r' (i.e., it's already been processed
+ through this code). Under some operating systems, native tools
+ may make all empty strings have the same index; but the pointer
+ check won't catch those, because to get to that stage we'd already
+ have to compute the checksum, which requires reading the string,
+ so we short-circuit that case with empty_string_index above. */
+ unsigned long pointer_matches;
+
+ /* Number of comparisons done. I figure with the algorithms in use below,
+ the average number of comparisons done (per symbol) should be roughly
+ log-base-2 of the number of unique strings. */
+ unsigned long n_compares;
+#endif
+};
+
+/* Some utility functions for the string table code. */
+
+/* For speed, only hash on the first this many bytes of strings.
+ This number was chosen by profiling ld linking itself, with -g. */
+#define HASHMAXLEN 25
+
+#define HASH_CHAR(c) (sum ^= sum >> 20, sum ^= sum << 7, sum += (c))
+
+static INLINE unsigned int
+hash (string, len)
+ unsigned char *string;
+ register unsigned int len;
+{
+ register unsigned int sum = 0;
+
+ if (len > HASHMAXLEN)
+ {
+ HASH_CHAR (len);
+ len = HASHMAXLEN;
+ }
+
+ while (len--)
+ {
+ HASH_CHAR (*string++);
+ }
+ return sum;
+}
+
+static INLINE void
+stringtab_init (tab)
+ struct stringtab_data *tab;
+{
+ tab->strings = 0;
+ tab->output_order = 0;
+ tab->end = &tab->output_order;
+
+ /* Initial string table length includes size of length field. */
+ tab->index = BYTES_IN_WORD;
+ tab->empty_string_index = -1;
+#ifdef GATHER_STATISTICS
+ tab->duplicates = 0;
+ tab->empty_strings = 0;
+ tab->bad_hash_matches = 0;
+ tab->pointer_matches = 0;
+ tab->bytes_saved = 0;
+ tab->n_compares = 0;
+#endif
+}
+
+static INLINE int
+compare (entry, str, hash)
+ struct stringtab_entry *entry;
+ CONST char *str;
+ unsigned int hash;
+{
+ return hash - entry->hash;
+}
+
+#ifdef GATHER_STATISTICS
+/* Don't want to have to link in math library with all bfd applications... */
+static INLINE double
+log2 (num)
+ int num;
+{
+ double d = num;
+ int n = 0;
+ while (d >= 2.0)
+ n++, d /= 2.0;
+ return ((d > 1.41) ? 0.5 : 0) + n;
+}
+#endif
+
+/* Main string table routines. */
+/* Returns index in string table. Whether or not this actually adds an
+ entry into the string table should be irrelevant -- it just has to
+ return a valid index. */
+static bfd_size_type
+add_to_stringtab (abfd, str, tab, check)
+ bfd *abfd;
+ CONST char *str;
+ struct stringtab_data *tab;
+ int check;
+{
+ struct stringtab_entry **ep;
+ register struct stringtab_entry *entry;
+ unsigned int hashval, len;
+
+ if (str[0] == 0)
+ {
+ bfd_size_type index;
+ CONST bfd_size_type minus_one = -1;
+
+#ifdef GATHER_STATISTICS
+ tab->empty_strings++;
+#endif
+ index = tab->empty_string_index;
+ if (index != minus_one)
+ {
+ got_empty:
+#ifdef GATHER_STATISTICS
+ tab->bytes_saved++;
+ tab->duplicates++;
+#endif
+ return index;
+ }
+
+ /* Need to find it. */
+ entry = tab->strings;
+ if (entry)
+ {
+ index = entry->index + strlen (entry->string);
+ tab->empty_string_index = index;
+ goto got_empty;
+ }
+ len = 0;
+ }
+ else
+ len = strlen (str);
+
+ /* The hash_zero value is chosen such that the first symbol gets a value of
+ zero. With a balanced tree, this wouldn't be very useful, but without it,
+ we might get a more even split at the top level, instead of skewing it
+ badly should hash("/usr/lib/crt0.o") (or whatever) be far from zero. */
+ hashval = hash (str, len) ^ tab->hash_zero;
+ ep = &tab->strings;
+ if (!*ep)
+ {
+ tab->hash_zero = hashval;
+ hashval = 0;
+ goto add_it;
+ }
+
+ while (*ep)
+ {
+ register int cmp;
+
+ entry = *ep;
+#ifdef GATHER_STATISTICS
+ tab->n_compares++;
+#endif
+ cmp = compare (entry, str, hashval);
+ /* The not-equal cases are more frequent, so check them first. */
+ if (cmp > 0)
+ ep = &entry->greater;
+ else if (cmp < 0)
+ ep = &entry->less;
+ else
+ {
+ if (entry->string == str)
+ {
+#ifdef GATHER_STATISTICS
+ tab->pointer_matches++;
+#endif
+ goto match;
+ }
+ /* Compare the first bytes to save a function call if they
+ don't match. */
+ if (entry->string[0] == str[0] && !strcmp (entry->string, str))
+ {
+ match:
+#ifdef GATHER_STATISTICS
+ entry->count++;
+ tab->bytes_saved += len + 1;
+ tab->duplicates++;
+#endif
+ /* If we're in the linker, and the new string is from a new
+ input file which might have already had these reductions
+ run over it, we want to keep the new string pointer. I
+ don't think we're likely to see any (or nearly as many,
+ at least) cases where a later string is in the same location
+ as an earlier one rather than this one. */
+ entry->string = str;
+ return entry->index;
+ }
+#ifdef GATHER_STATISTICS
+ tab->bad_hash_matches++;
+#endif
+ ep = &entry->greater;
+ }
+ }
+
+ /* If we get here, nothing that's in the table already matched.
+ EP points to the `next' field at the end of the chain; stick a
+ new entry on here. */
+ add_it:
+ entry = (struct stringtab_entry *)
+ bfd_alloc_by_size_t (abfd, sizeof (struct stringtab_entry));
+
+ entry->less = entry->greater = 0;
+ entry->hash = hashval;
+ entry->index = tab->index;
+ entry->string = str;
+ entry->next_to_output = 0;
+#ifdef GATHER_STATISTICS
+ entry->count = 1;
+#endif
+
+ assert (*tab->end == 0);
+ *(tab->end) = entry;
+ tab->end = &entry->next_to_output;
+ assert (*tab->end == 0);
+
+ {
+ tab->index += len + 1;
+ if (len == 0)
+ tab->empty_string_index = entry->index;
+ }
+ assert (*ep == 0);
+ *ep = entry;
+ return entry->index;
+}
+
+static void
+emit_strtab (abfd, tab)
+ bfd *abfd;
+ struct stringtab_data *tab;
+{
+ struct stringtab_entry *entry;
+#ifdef GATHER_STATISTICS
+ int count = 0;
+#endif
+
+ /* Be sure to put string length into correct byte ordering before writing
+ it out. */
+ char buffer[BYTES_IN_WORD];
+
+ PUT_WORD (abfd, tab->index, (unsigned char *) buffer);
+ bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd);
+
+ for (entry = tab->output_order; entry; entry = entry->next_to_output)
+ {
+ bfd_write ((PTR) entry->string, 1, strlen (entry->string) + 1, abfd);
+#ifdef GATHER_STATISTICS
+ count++;
+#endif
+ }
+
+#ifdef GATHER_STATISTICS
+ /* Short form only, for now.
+ To do: Specify output file. Conditionalize on environment? Detailed
+ analysis if desired. */
+ {
+ int n_syms = bfd_get_symcount (abfd);
+
+ fprintf (stderr, "String table data for output file:\n");
+ fprintf (stderr, " %8d symbols output\n", n_syms);
+ fprintf (stderr, " %8d duplicate strings\n", tab->duplicates);
+ fprintf (stderr, " %8d empty strings\n", tab->empty_strings);
+ fprintf (stderr, " %8d unique strings output\n", count);
+ fprintf (stderr, " %8d pointer matches\n", tab->pointer_matches);
+ fprintf (stderr, " %8d bytes saved\n", tab->bytes_saved);
+ fprintf (stderr, " %8d bad hash matches\n", tab->bad_hash_matches);
+ fprintf (stderr, " %8d hash-val comparisons\n", tab->n_compares);
+ if (n_syms)
+ {
+ double n_compares = tab->n_compares;
+ double avg_compares = n_compares / n_syms;
+ /* The second value here should usually be near one. */
+ fprintf (stderr,
+ "\t average %f comparisons per symbol (%f * log2 nstrings)\n",
+ avg_compares, avg_compares / log2 (count));
+ }
+ }
+#endif
+
+/* Old code:
+ unsigned int count;
+ generic = bfd_get_outsymbols(abfd);
+ for (count = 0; count < bfd_get_symcount(abfd); count++)
+ {
+ asymbol *g = *(generic++);
+
+ if (g->name)
+ {
+ size_t length = strlen(g->name)+1;
+ bfd_write((PTR)g->name, 1, length, abfd);
+ }
+ g->KEEPIT = (KEEPITTYPE) count;
+ } */
+}
+
+void
+DEFUN(NAME(aout,write_syms),(abfd),
+ bfd *abfd)
+{
+ unsigned int count ;
+ asymbol **generic = bfd_get_outsymbols (abfd);
+ struct stringtab_data strtab;
+
+ stringtab_init (&strtab);
+
+ for (count = 0; count < bfd_get_symcount (abfd); count++)
+ {
+ asymbol *g = generic[count];
+ struct external_nlist nsp;
+
+ if (g->name)
+ PUT_WORD (abfd, add_to_stringtab (abfd, g->name, &strtab),
+ (unsigned char *) nsp.e_strx);
+ else
+ PUT_WORD (abfd, 0, (unsigned char *)nsp.e_strx);
+
+ if (bfd_asymbol_flavour(g) == abfd->xvec->flavour)
+ {
+ bfd_h_put_16(abfd, aout_symbol(g)->desc, nsp.e_desc);
+ bfd_h_put_8(abfd, aout_symbol(g)->other, nsp.e_other);
+ bfd_h_put_8(abfd, aout_symbol(g)->type, nsp.e_type);
+ }
+ else
+ {
+ bfd_h_put_16(abfd,0, nsp.e_desc);
+ bfd_h_put_8(abfd, 0, nsp.e_other);
+ bfd_h_put_8(abfd, 0, nsp.e_type);
+ }
+
+ translate_to_native_sym_flags (&nsp, g, abfd);
+
+ bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd);
+
+ /* NB: `KEEPIT' currently overlays `flags', so set this only
+ here, at the end. */
+ g->KEEPIT = count;
+ }
+
+ emit_strtab (abfd, &strtab);
+}
+
+
+unsigned int
+DEFUN(NAME(aout,get_symtab),(abfd, location),
+ bfd *abfd AND
+ asymbol **location)
+{
+ unsigned int counter = 0;
+ aout_symbol_type *symbase;
+
+ if (!NAME(aout,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);
+}
+
+
+/* Standard reloc stuff */
+/* Output standard relocation information to a file in target byte order. */
+
+void
+DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr),
+ bfd *abfd AND
+ arelent *g AND
+ struct reloc_std_external *natptr)
+{
+ int r_index;
+ asymbol *sym = *(g->sym_ptr_ptr);
+ int r_extern;
+ unsigned int r_length;
+ int r_pcrel;
+ int r_baserel, r_jmptable, r_relative;
+ unsigned int r_addend;
+ asection *output_section = sym->section->output_section;
+
+ PUT_WORD(abfd, g->address, natptr->r_address);
+
+ r_length = g->howto->size ; /* Size as a power of two */
+ r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
+ /* XXX This relies on relocs coming from a.out files. */
+ r_baserel = (g->howto->type & 8) != 0;
+ /* r_jmptable, r_relative??? FIXME-soon */
+ r_jmptable = 0;
+ r_relative = 0;
+
+ r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
+
+ /* name was clobbered by aout_write_syms to be symbol index */
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ check for that here
+ */
+
+
+ if (bfd_is_com_section (output_section)
+ || output_section == &bfd_abs_section
+ || output_section == &bfd_und_section)
+ {
+ if (bfd_abs_section.symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_index = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ /* Fill in symbol */
+ r_extern = 1;
+ r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT);
+
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+ /* 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_type[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_type[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
+DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr),
+ bfd *abfd AND
+ arelent *g AND
+ register struct reloc_ext_external *natptr)
+{
+ int r_index;
+ int r_extern;
+ unsigned int r_type;
+ unsigned int r_addend;
+ asymbol *sym = *(g->sym_ptr_ptr);
+ asection *output_section = sym->section->output_section;
+
+ PUT_WORD (abfd, g->address, natptr->r_address);
+
+ r_type = (unsigned int) g->howto->type;
+
+ r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ check for that here. */
+
+ if (bfd_is_com_section (output_section)
+ || output_section == &bfd_abs_section
+ || output_section == &bfd_und_section)
+ {
+ if (bfd_abs_section.symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_index = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ r_extern = 1;
+ r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT);
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+ /* 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_type[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_type[0] =
+ (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
+ | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
+ }
+
+ PUT_WORD (abfd, r_addend, natptr->r_addend);
+}
+
+/* BFD deals internally with all things based from the section they're
+ in. so, something in 10 bytes into a text section with a base of
+ 50 would have a symbol (.text+10) and know .text vma was 50.
+
+ Aout keeps all it's symbols based from zero, so the symbol would
+ contain 60. This macro subs the base of each section from the value
+ to give the true offset from the section */
+
+
+#define MOVE_ADDRESS(ad) \
+ if (r_extern) { \
+ /* undefined symbol */ \
+ cache_ptr->sym_ptr_ptr = symbols + r_index; \
+ cache_ptr->addend = ad; \
+ } else { \
+ /* defined, section relative. replace symbol with pointer to \
+ symbol which points to section */ \
+ switch (r_index) { \
+ case N_TEXT: \
+ case N_TEXT | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->textsec->vma; \
+ break; \
+ case N_DATA: \
+ case N_DATA | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->datasec->vma; \
+ break; \
+ case N_BSS: \
+ case N_BSS | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->bsssec->vma; \
+ break; \
+ default: \
+ case N_ABS: \
+ case N_ABS | N_EXT: \
+ cache_ptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr; \
+ cache_ptr->addend = ad; \
+ break; \
+ } \
+ } \
+
+void
+DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols),
+ bfd *abfd AND
+ struct reloc_ext_external *bytes AND
+ arelent *cache_ptr AND
+ asymbol **symbols)
+{
+ int r_index;
+ int r_extern;
+ unsigned int r_type;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+
+ cache_ptr->address = (GET_SWORD (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_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
+ r_type = (bytes->r_type[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_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
+ r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
+ >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
+ }
+
+ cache_ptr->howto = howto_table_ext + r_type;
+ MOVE_ADDRESS(GET_SWORD(abfd, bytes->r_addend));
+}
+
+void
+DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols),
+ bfd *abfd AND
+ struct reloc_std_external *bytes AND
+ arelent *cache_ptr AND
+ asymbol **symbols)
+{
+ int r_index;
+ int r_extern;
+ unsigned int r_length;
+ int r_pcrel;
+ int r_baserel, r_jmptable, r_relative;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+ int howto_idx;
+
+ cache_ptr->address = bfd_h_get_32 (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_type[0] & RELOC_STD_BITS_EXTERN_BIG));
+ r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
+ r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
+ r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
+ r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
+ r_length = (bytes->r_type[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_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
+ r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
+ r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
+ r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
+ r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
+ r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
+ >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
+ }
+
+ howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel;
+ BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std));
+ cache_ptr->howto = howto_table_std + howto_idx;
+ BFD_ASSERT (cache_ptr->howto->type != -1);
+ BFD_ASSERT (r_jmptable == 0);
+ BFD_ASSERT (r_relative == 0);
+ /* FIXME-soon: Roll jmptable, relative bits into howto setting */
+
+ MOVE_ADDRESS(0);
+}
+
+/* Reloc hackery */
+
+boolean
+DEFUN(NAME(aout,slurp_reloc_table),(abfd, asect, symbols),
+ bfd *abfd AND
+ sec_ptr asect AND
+ asymbol **symbols)
+{
+ unsigned int count;
+ bfd_size_type reloc_size;
+ PTR 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 = obj_reloc_entry_size (abfd);
+
+ count = reloc_size / each_size;
+
+
+ reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
+ (arelent)));
+ if (!reloc_cache) {
+nomem:
+ bfd_error = no_memory;
+ return false;
+ }
+
+ relocs = (PTR) bfd_alloc (abfd, reloc_size);
+ if (!relocs) {
+ bfd_release (abfd, reloc_cache);
+ goto nomem;
+ }
+
+ if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
+ bfd_release (abfd, relocs);
+ bfd_release (abfd, reloc_cache);
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ if (each_size == RELOC_EXT_SIZE) {
+ register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
+ unsigned int counter = 0;
+ arelent *cache_ptr = reloc_cache;
+
+ for (; counter < count; counter++, rptr++, cache_ptr++) {
+ NAME(aout,swap_ext_reloc_in)(abfd, rptr, cache_ptr, symbols);
+ }
+ } else {
+ register struct reloc_std_external *rptr = (struct reloc_std_external*) relocs;
+ unsigned int counter = 0;
+ arelent *cache_ptr = reloc_cache;
+
+ for (; counter < count; counter++, rptr++, cache_ptr++) {
+ NAME(aout,swap_std_reloc_in)(abfd, rptr, cache_ptr, symbols);
+ }
+
+ }
+
+ bfd_release (abfd,relocs);
+ asect->relocation = reloc_cache;
+ asect->reloc_count = count;
+ return true;
+}
+
+
+
+/* Write out a relocation section into an object file. */
+
+boolean
+DEFUN(NAME(aout,squirt_out_relocs),(abfd, section),
+ bfd *abfd AND
+ asection *section)
+{
+ arelent **generic;
+ unsigned char *native, *natptr;
+ size_t each_size;
+
+ unsigned int count = section->reloc_count;
+ size_t natsize;
+
+ if (count == 0) return true;
+
+ each_size = obj_reloc_entry_size (abfd);
+ natsize = each_size * count;
+ native = (unsigned char *) bfd_zalloc (abfd, natsize);
+ if (!native) {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ generic = section->orelocation;
+
+ if (each_size == RELOC_EXT_SIZE)
+ {
+ for (natptr = native;
+ count != 0;
+ --count, natptr += each_size, ++generic)
+ NAME(aout,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *)natptr);
+ }
+ else
+ {
+ for (natptr = native;
+ count != 0;
+ --count, natptr += each_size, ++generic)
+ NAME(aout,swap_std_reloc_out)(abfd, *generic, (struct reloc_std_external *)natptr);
+ }
+
+ if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
+ bfd_release(abfd, native);
+ return false;
+ }
+ bfd_release (abfd, native);
+
+ return true;
+}
+
+/* This is stupid. This function should be a boolean predicate */
+unsigned int
+DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols),
+ bfd *abfd AND
+ sec_ptr section AND
+ arelent **relptr AND
+ asymbol **symbols)
+{
+ arelent *tblptr = section->relocation;
+ unsigned int count;
+
+ if (!(tblptr || NAME(aout,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
+DEFUN(NAME(aout,get_reloc_upper_bound),(abfd, asect),
+ bfd *abfd AND
+ 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 / obj_reloc_entry_size (abfd))
+ +1));
+
+ if (asect == obj_textsec (abfd))
+ return (sizeof (arelent *) *
+ ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
+ +1));
+
+ bfd_error = invalid_operation;
+ return 0;
+}
+
+
+ unsigned int
+DEFUN(NAME(aout,get_symtab_upper_bound),(abfd),
+ bfd *abfd)
+{
+ if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
+
+ return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
+}
+ alent *
+DEFUN(NAME(aout,get_lineno),(ignore_abfd, ignore_symbol),
+ bfd *ignore_abfd AND
+ asymbol *ignore_symbol)
+{
+return (alent *)NULL;
+}
+
+void
+DEFUN(NAME(aout,get_symbol_info),(ignore_abfd, symbol, ret),
+ bfd *ignore_abfd AND
+ asymbol *symbol AND
+ symbol_info *ret)
+{
+ bfd_symbol_info (symbol, ret);
+
+ if (ret->type == '?')
+ {
+ int type_code = aout_symbol(symbol)->type & 0xff;
+ CONST char *stab_name = aout_stab_name(type_code);
+ static char buf[10];
+
+ if (stab_name == NULL)
+ {
+ sprintf(buf, "(%d)", type_code);
+ stab_name = buf;
+ }
+ ret->type = '-';
+ ret->stab_other = (unsigned)(aout_symbol(symbol)->other & 0xff);
+ ret->stab_desc = (unsigned)(aout_symbol(symbol)->desc & 0xffff);
+ ret->stab_name = stab_name;
+ }
+}
+
+void
+DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how),
+ bfd *ignore_abfd AND
+ PTR afile AND
+ asymbol *symbol AND
+ bfd_print_symbol_type how)
+{
+ FILE *file = (FILE *)afile;
+
+ switch (how) {
+ case bfd_print_symbol_name:
+ if (symbol->name)
+ fprintf(file,"%s", symbol->name);
+ break;
+ case bfd_print_symbol_more:
+ 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:
+ {
+ CONST char *section_name = symbol->section->name;
+
+
+ bfd_print_symbol_vandf((PTR)file,symbol);
+
+ fprintf(file," %-5s %04x %02x %02x",
+ section_name,
+ (unsigned)(aout_symbol(symbol)->desc & 0xffff),
+ (unsigned)(aout_symbol(symbol)->other & 0xff),
+ (unsigned)(aout_symbol(symbol)->type & 0xff));
+ if (symbol->name)
+ fprintf(file," %s", symbol->name);
+ }
+ break;
+ }
+}
+
+/*
+ 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
+DEFUN(NAME(aout,find_nearest_line),(abfd,
+ section,
+ symbols,
+ offset,
+ filename_ptr,
+ functionname_ptr,
+ line_ptr),
+ bfd *abfd AND
+ asection *section AND
+ asymbol **symbols AND
+ bfd_vma offset AND
+ CONST char **filename_ptr AND
+ CONST char **functionname_ptr AND
+ unsigned int *line_ptr)
+{
+ /* Run down the file looking for the filename, function and linenumber */
+ asymbol **p;
+ static char buffer[100];
+ static char filename_buffer[200];
+ CONST char *directory_name = NULL;
+ CONST char *main_file_name = NULL;
+ CONST char *current_file_name = NULL;
+ CONST char *line_file_name = NULL; /* Value of current_file_name at line number. */
+ 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);
+ next:
+ switch (q->type){
+ case N_SO:
+ main_file_name = current_file_name = q->symbol.name;
+ /* Look ahead to next symbol to check if that too is an N_SO. */
+ p++;
+ if (*p == NULL)
+ break;
+ q = (aout_symbol_type *)(*p);
+ if (q->type != (int)N_SO)
+ goto next;
+
+ /* Found a second N_SO First is directory; second is filename. */
+ directory_name = current_file_name;
+ main_file_name = current_file_name = q->symbol.name;
+ if (obj_textsec(abfd) != section)
+ goto done;
+ break;
+ case N_SOL:
+ current_file_name = q->symbol.name;
+ 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;
+ line_file_name = current_file_name;
+ }
+ 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) {
+ CONST 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 = '\0'; }
+ *functionname_ptr = buffer;
+ goto done;
+
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ done:
+ if (*line_ptr)
+ main_file_name = line_file_name;
+ if (main_file_name) {
+ if (main_file_name[0] == '/' || directory_name == NULL)
+ *filename_ptr = main_file_name;
+ else {
+ sprintf(filename_buffer, "%.140s%.50s",
+ directory_name, main_file_name);
+ *filename_ptr = filename_buffer;
+ }
+ }
+ return true;
+
+}
+
+int
+DEFUN(NAME(aout,sizeof_headers),(abfd, execable),
+ bfd *abfd AND
+ boolean execable)
+{
+ return adata(abfd).exec_bytes_size;
+}
diff --git a/gnu/usr.bin/gdb/bfd/archive.c b/gnu/usr.bin/gdb/bfd/archive.c
new file mode 100644
index 000000000000..5edae9d3db0a
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/archive.c
@@ -0,0 +1,1770 @@
+/* BFD back-end for archive files (libraries).
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+@setfilename archive-info
+SECTION
+ Archives
+
+DESCRIPTION
+ Archives are supported in BFD in <<archive.c>>.
+
+ An archive (or library) is just another BFD. It has a symbol
+ table, although there's not much a user program will do with it.
+
+ The big difference between an archive BFD and an ordinary BFD
+ is that the archive doesn't have sections. Instead it has a
+ chain of BFDs considered its contents. These BFDs can be
+ manipulated just like any other. The BFDs contained in an
+ archive opened for reading will all be opened for reading; you
+ may put either input or output BFDs into an archive opened for
+ output; it will be handled correctly when the archive is closed.
+
+ Use <<bfd_openr_next_archived_file>> to step through all
+ the contents of an archive opened for input. It's not
+ required that you read the entire archive if you don't want
+ to! Read it until you find what you want.
+
+ Archive contents of output BFDs are chained through the
+ <<next>> pointer in a BFD. The first one is findable through
+ the <<archive_head>> slot of the archive. Set it with
+ <<set_archive_head>> (q.v.). A given BFD may be in only one
+ open output archive at a time.
+
+ As expected, the BFD archive code is more general than the
+ archive code of any given environment. BFD archives may
+ contain files of different formats (e.g., a.out and coff) and
+ even different architectures. You may even place archives
+ recursively into archives!
+
+ This can cause unexpected confusion, since some archive
+ formats are more expressive than others. For instance, Intel
+ COFF archives can preserve long filenames; Sun a.out archives
+ cannot. If you move a file from the first to the second
+ format and back again, the filename may be truncated.
+ Likewise, different a.out environments have different
+ conventions as to how they truncate filenames, whether they
+ preserve directory names in filenames, etc. When
+ interoperating with native tools, be sure your files are
+ homogeneous.
+
+ Beware: most of these formats do not react well to the
+ presence of spaces in filenames. We do the best we can, but
+ can't always handle this due to restrctions in the format of
+ archives. Many unix utilities are braindead in regards to
+ spaces and such in filenames anyway, so this shouldn't be much
+ of a restriction.
+*/
+
+/* 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).
+*/
+
+/* Some formats provide a way to cram a long filename into the short
+ (16 chars) space provided by a bsd archive. The trick is: make a
+ special "file" in the front of the archive, sort of like the SYMDEF
+ entry. If the filename is too long to fit, put it in the extended
+ name table, and use its index as the filename. To prevent
+ confusion prepend the index with a space. This means you can't
+ have filenames that start with a space, but then again, many unix
+ utilities can't handle that anyway.
+
+ This scheme unfortunately requires that you stand on your head in
+ order to write an archive since you need to put a magic file at the
+ front, and need to touch every entry to do so. C'est la vie.
+
+ We support two variants of this idea:
+ The SVR4 format (extended name table is named "//"),
+ and an extended pseudo-BSD variant (extended name table is named
+ "ARFILENAMES/"). The origin of the latter format is uncertain.
+
+ BSD 4.4 uses a third scheme: It writes a long filename
+ directly after the header. This allows 'ar q' to work.
+ We current can read BSD 4.4 archives, but not write them.
+*/
+
+/* Summary of archive member names:
+
+ Symbol table (must be first):
+ "__.SYMDEF " - Symbol table, Berkeley style, produced by ranlib.
+ "/ " - Symbol table, system 5 style.
+
+ Long name table (must be before regular file members):
+ "// " - Long name table, System 5 R4 style.
+ "ARFILENAMES/ " - Long name table, non-standard extended BSD (not BSD 4.4).
+
+ Regular file members with short names:
+ "filename.o/ " - Regular file, System 5 style (embedded spaces ok).
+ "filename.o " - Regular file, Berkeley style (no embedded spaces).
+
+ Regular files with long names (or embedded spaces, for BSD variants):
+ "/18 " - SVR4 style, name at offset 18 in name table.
+ "#1/23 " - Long name (or embedded paces) 23 characters long,
+ BSD 4.4 style, full name follows header.
+ Implemented for reading, not writing.
+ " 18 " - Long name 18 characters long, extended pseudo-BSD.
+ */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "aout/ar.h"
+#include "aout/ranlib.h"
+#include <errno.h>
+#include <string.h> /* For memchr, strrchr and friends */
+#include <ctype.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef GNU960
+#define BFD_GNU960_ARMAG(abfd) (BFD_COFF_FILE_P((abfd)) ? ARMAG : ARMAGB)
+#endif
+
+/* Can't define this in hosts/*.h, because (e.g. in gprof) the hosts file
+ is included, then obstack.h, which thinks if offsetof is defined, it
+ doesn't need to include stddef.h. */
+/* Define offsetof for those systems which lack it */
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* 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 generally 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_eltdata(bfd) ((struct areltdata *)((bfd)->arelt_data))
+#define arch_hdr(bfd) ((struct ar_hdr *)arch_eltdata(bfd)->arch_header)
+
+/* Forward declarations of functions */
+
+boolean
+compute_and_write_armap PARAMS ((bfd *arch, unsigned int elength));
+
+static boolean
+bsd_update_armap_timestamp PARAMS ((bfd *arch));
+
+
+
+boolean
+_bfd_generic_mkarchive (abfd)
+ bfd *abfd;
+{
+ abfd->tdata.aout_ar_data = (struct artdata *)bfd_zalloc(abfd,
+ sizeof (struct artdata));
+
+ if (bfd_ardata (abfd) == NULL) {
+ bfd_error = no_memory;
+ return false;
+ }
+ bfd_ardata(abfd)->cache = 0;
+ return true;
+}
+
+/*
+FUNCTION
+ bfd_get_next_mapent
+
+SYNOPSIS
+ symindex bfd_get_next_mapent(bfd *, symindex previous, carsym ** sym);
+
+DESCRIPTION
+ This function steps through an archive's symbol table (if it
+ has one). Successively updates <<sym>> with the next symbol's
+ information, returning that symbol's (internal) index into the
+ symbol table.
+
+ Supply BFD_NO_MORE_SYMBOLS as the <<previous>> entry to get
+ the first one; returns BFD_NO_MORE_SYMBOLS when you're already
+ got the last one.
+
+ A <<carsym>> is a canonical archive symbol. The only
+ user-visible element is its name, a null-terminated string.
+*/
+
+symindex
+DEFUN(bfd_get_next_mapent,(abfd, prev, entry),
+ bfd *abfd AND
+ symindex prev AND
+ 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 >= 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;
+}
+
+/*
+FUNCTION
+ bfd_set_archive_head
+
+SYNOPSIS
+ boolean bfd_set_archive_head(bfd *output, bfd *new_head);
+
+DESCRIPTION
+ Used whilst processing archives. Sets the head of the chain of
+ BFDs contained in an archive to @var{new_head}.
+*/
+
+boolean
+DEFUN(bfd_set_archive_head,(output_archive, new_head),
+ bfd *output_archive AND
+ bfd *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 *)
+ bfd_zalloc(arch_bfd, 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;
+}
+
+
+
+/* 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;
+{
+ 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;
+ /* Skip first char, which is '/' in SVR4 or ' ' in some other variants. */
+ index = strtol (name+1, 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;
+{
+#ifndef errno
+ extern int errno;
+#endif
+
+ 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 = 0;
+
+ if (bfd_read ((PTR)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 - there are two ways to
+ specify an extendend name table, either the first char of the
+ name is a space, or it's a slash. */
+ if ((hdr.ar_name[0] == '/'
+ || (hdr.ar_name[0] == ' '
+ && memchr (hdr.ar_name, '/', ar_maxnamelen(abfd)) == NULL))
+ && bfd_ardata (abfd)->extended_names != NULL) {
+ filename = get_extended_arelt_filename (abfd, hdr.ar_name);
+ if (filename == NULL) {
+ bfd_error = malformed_archive;
+ return NULL;
+ }
+ }
+ /* BSD4.4-style long filename.
+ Only implemented for reading, so far! */
+ else if (hdr.ar_name[0] == '#' && hdr.ar_name[1] == '1'
+ && hdr.ar_name[2] == '/' && isdigit(hdr.ar_name[3]))
+ {
+ /* BSD-4.4 extended name */
+ namelen = atoi (&hdr.ar_name[3]);
+ allocsize += namelen + 1;
+ parsed_size -= namelen;
+
+ allocptr = bfd_zalloc(abfd, allocsize);
+ if (allocptr == NULL) {
+ bfd_error = no_memory;
+ return NULL;
+ }
+ filename = allocptr
+ + (sizeof (struct areltdata) + sizeof (struct ar_hdr));
+ if (bfd_read (filename, 1, namelen, abfd) != namelen) {
+ bfd_error = no_more_archived_files;
+ return NULL;
+ }
+ filename[namelen] = '\0';
+ }
+ else
+ {
+ /* We judge the end of the name by looking for '/' or ' '.
+ Note: The SYSV format (terminated by '/') allows embedded
+ spaces, so only look for ' ' if we don't find '/'. */
+
+ namelen = 0;
+ while (hdr.ar_name[namelen] != '\0' &&
+ hdr.ar_name[namelen] != '/') {
+ namelen++;
+ if (namelen == (unsigned)ar_maxnamelen(abfd)) {
+ namelen = 0;
+ while (hdr.ar_name[namelen] != ' '
+ && namelen < (unsigned)ar_maxnamelen(abfd)) {
+ namelen++;
+ }
+ break;
+ }
+ }
+
+ allocsize += namelen + 1;
+ }
+
+ if (!allocptr) {
+ allocptr = bfd_zalloc(abfd, 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, (char *) &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;
+}
+
+/* This is an internal function; it's mainly used when indexing
+ through the archive symbol table, but also used to get the next
+ element, since it handles the bookkeeping so nicely for us.
+*/
+
+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)
+ {
+ bfd_release (archive, (PTR)new_areldata);
+ return NULL;
+ }
+
+ n_nfd->origin = bfd_tell (archive);
+ n_nfd->arelt_data = (PTR) new_areldata;
+ n_nfd->filename = new_areldata->filename;
+
+ if (add_bfd_to_cache (archive, filepos, n_nfd))
+ return n_nfd;
+
+ /* huh? */
+ bfd_release (archive, (PTR)n_nfd);
+ bfd_release (archive, (PTR)new_areldata);
+ return NULL;
+}
+
+/*
+FUNCTION
+ bfd_get_elt_at_index
+
+SYNOPSIS
+ bfd *bfd_get_elt_at_index(bfd * archive, int index);
+
+DESCRIPTION
+ Return the bfd which is referenced by the symbol indexed by <<index>>.
+ <<index>> should have been returned by <<bfd_get_next_mapent>> (q.v.).
+
+*/
+bfd *
+DEFUN(bfd_get_elt_at_index,(abfd, index),
+ bfd *abfd AND
+ int index)
+{
+ bfd *result =
+ get_elt_at_filepos
+ (abfd, (bfd_ardata (abfd)->symdefs + index)->file_offset);
+ return result;
+}
+
+/*
+FUNCTION
+ bfd_openr_next_archived_file
+
+SYNOPSIS
+ bfd* bfd_openr_next_archived_file(bfd *archive, bfd *previous);
+
+DESCRIPTION
+ Initially provided a BFD containing an archive and NULL, opens
+ an inpout BFD on the first contained element and returns that.
+ Subsequent calls to bfd_openr_next_archived_file should pass
+ the archive and the previous return value to return a created
+ BFD to the next contained element. NULL is returned when there
+ are no more.
+
+*/
+
+bfd *
+bfd_openr_next_archived_file (archive, last_file)
+ bfd *archive;
+ bfd *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);
+ /* Pad to an even boundary...
+ Note that last_file->origin can be odd in the case of
+ BSD-4.4-style element with a long odd size. */
+ filestart = last_file->origin + size;
+ filestart += filestart % 2;
+ }
+
+ return get_elt_at_filepos (archive, filestart);
+}
+
+
+bfd_target *
+bfd_generic_archive_p (abfd)
+ bfd *abfd;
+{
+ char armag[SARMAG+1];
+
+ if (bfd_read ((PTR)armag, 1, SARMAG, abfd) != SARMAG) {
+ bfd_error = wrong_format;
+ return 0;
+ }
+
+#ifdef GNU960
+ if (strncmp (armag, BFD_GNU960_ARMAG(abfd), SARMAG)) return 0;
+#else
+ if (strncmp (armag, ARMAG, SARMAG) &&
+ strncmp (armag, ARMAGB, SARMAG)) return 0;
+#endif
+
+
+
+ /* We are setting bfd_ardata(abfd) here, but since bfd_ardata
+ involves a cast, we can't do it as the left operand of assignment. */
+ abfd->tdata.aout_ar_data = (struct artdata *) bfd_zalloc(abfd,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))) {
+ bfd_release(abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = NULL;
+ return 0;
+ }
+
+ if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) {
+ bfd_release(abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = NULL;
+ return 0;
+ }
+
+ return abfd->xvec;
+}
+
+/* Returns false on error, true otherwise */
+static boolean
+DEFUN (do_slurp_bsd_armap, (abfd),
+ bfd *abfd)
+{
+ struct areltdata *mapdata;
+ unsigned int counter = 0;
+ int *raw_armap, *rbase;
+ struct artdata *ardata = bfd_ardata (abfd);
+ char *stringbase;
+ unsigned int parsed_size;
+
+ mapdata = snarf_ar_hdr (abfd);
+ if (mapdata == NULL) return false;
+ parsed_size = mapdata->parsed_size;
+ bfd_release (abfd, (PTR)mapdata); /* Don't need it any more. */
+
+ raw_armap = (int *) bfd_zalloc(abfd, parsed_size);
+ if (raw_armap == NULL) {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ if (bfd_read ((PTR)raw_armap, 1, parsed_size, abfd) != parsed_size) {
+ bfd_error = malformed_archive;
+ byebye:
+ bfd_release (abfd, (PTR)raw_armap);
+ return false;
+ }
+
+ ardata->symdef_count =
+ bfd_h_get_32(abfd, (PTR)raw_armap) / sizeof (struct symdef);
+
+ if (ardata->symdef_count * sizeof (struct symdef)
+ > parsed_size - sizeof (*raw_armap)) {
+ /* Probably we're using the wrong byte ordering. */
+ bfd_error = wrong_format;
+ goto byebye;
+ }
+
+ ardata->cache = 0;
+ rbase = raw_armap+1;
+ ardata->symdefs = (carsym *) rbase;
+ stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4;
+
+ for (;counter < ardata->symdef_count; counter++) {
+ struct symdef *sym = ((struct symdef *) rbase) + counter;
+ sym->s.name = bfd_h_get_32(abfd, (PTR)(&(sym->s.string_offset))) + stringbase;
+ sym->file_offset = bfd_h_get_32(abfd, (PTR)( &(sym->file_offset)));
+ }
+
+ 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;
+ /* FIXME, we should provide some way to free raw_ardata when
+ we are done using the strings from it. For now, it seems
+ to be allocated on an obstack anyway... */
+ bfd_has_map (abfd) = true;
+ return true;
+}
+
+/* Returns false on error, true otherwise */
+static boolean
+DEFUN (do_slurp_coff_armap, (abfd),
+ bfd *abfd)
+{
+ struct areltdata *mapdata;
+ int *raw_armap, *rawptr;
+ struct artdata *ardata = bfd_ardata (abfd);
+ char *stringbase;
+ unsigned int stringsize;
+ unsigned int parsed_size;
+ carsym *carsyms;
+ unsigned int nsymz; /* Number of symbols in armap. */
+
+ bfd_vma (*swap) PARAMS ((bfd_byte*));
+ char int_buf[sizeof(long)];
+ unsigned int carsym_size, ptrsize, i;
+
+ mapdata = snarf_ar_hdr (abfd);
+ if (mapdata == NULL) return false;
+ parsed_size = mapdata->parsed_size;
+ bfd_release (abfd, (PTR)mapdata); /* Don't need it any more. */
+
+ if (bfd_read ((PTR)int_buf, 1, 4, abfd) != 4) {
+ bfd_error = malformed_archive;
+ return false;
+ }
+ /* It seems that all numeric information in a coff archive is always
+ in big endian format, nomatter the host or target. */
+ swap = bfd_getb32;
+ nsymz = bfd_getb32((PTR)int_buf);
+ stringsize = parsed_size - (4 * nsymz) - 4;
+
+#if 1
+ /* ... except that some archive formats are broken, and it may be our
+ fault - the i960 little endian coff sometimes has big and sometimes
+ little, because our tools changed. Here's a horrible hack to clean
+ up the crap. */
+
+ if (stringsize > 0xfffff) {
+ /* This looks dangerous, let's do it the other way around */
+ nsymz = bfd_getl32((PTR)int_buf);
+ stringsize = parsed_size - (4 * nsymz) - 4;
+ swap = bfd_getl32;
+ }
+#endif
+
+ /* The coff armap must be read sequentially. So we construct a bsd-style
+ one in core all at once, for simplicity. */
+
+ carsym_size = (nsymz * sizeof (carsym));
+ ptrsize = (4 * nsymz);
+
+ ardata->symdefs = (carsym *) bfd_zalloc(abfd, carsym_size + stringsize + 1);
+ if (ardata->symdefs == NULL) {
+ bfd_error = no_memory;
+ return false;
+ }
+ carsyms = ardata->symdefs;
+ stringbase = ((char *) ardata->symdefs) + carsym_size;
+
+ /* Allocate and read in the raw offsets. */
+ raw_armap = (int *) bfd_alloc(abfd, ptrsize);
+ if (raw_armap == NULL) {
+ bfd_error = no_memory;
+ goto release_symdefs;
+ }
+ if (bfd_read ((PTR)raw_armap, 1, ptrsize, abfd) != ptrsize
+ || bfd_read ((PTR)stringbase, 1, stringsize, abfd) != stringsize) {
+ bfd_error = malformed_archive;
+ goto release_raw_armap;
+ }
+
+ /* OK, build the carsyms */
+ for (i = 0; i < nsymz; i++) {
+ rawptr = raw_armap + i;
+ carsyms->file_offset = swap((PTR)rawptr);
+ carsyms->name = stringbase;
+ while (*stringbase++) ;
+ carsyms++;
+ }
+ *stringbase = 0;
+
+ ardata->symdef_count = nsymz;
+ 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;
+
+ bfd_has_map (abfd) = true;
+ bfd_release (abfd, (PTR)raw_armap);
+ return true;
+
+ release_raw_armap:
+ bfd_release (abfd, (PTR)raw_armap);
+ release_symdefs:
+ bfd_release (abfd, (PTR)(ardata)->symdefs);
+ return false;
+}
+
+/* This routine can handle either coff-style or bsd-style armaps.
+ Returns false on error, true otherwise */
+
+boolean
+bfd_slurp_armap (abfd)
+ bfd *abfd;
+{
+ char nextname[17];
+ int i = bfd_read ((PTR)nextname, 1, 16, abfd);
+
+ if (i == 0)
+ return true;
+ if (i != 16)
+ return false;
+
+ bfd_seek (abfd, (file_ptr) -16, SEEK_CUR);
+
+ if (!strncmp (nextname, "__.SYMDEF ", 16))
+ return do_slurp_bsd_armap (abfd);
+ else if (!strncmp (nextname, "/ ", 16))
+ return do_slurp_coff_armap (abfd);
+
+ bfd_has_map (abfd) = false;
+ return true;
+}
+
+/* Returns false on error, true otherwise */
+/* flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the
+ header is in a slightly different order and the map name is '/'.
+ This flavour is used by hp300hpux. */
+boolean
+bfd_slurp_bsd_armap_f2 (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;
+ unsigned int stringsize;
+ int i = bfd_read ((PTR)nextname, 1, 16, abfd);
+
+ if (i == 0)
+ return true;
+ if (i != 16)
+ return false;
+
+ /* The archive has at least 16 bytes in it */
+ bfd_seek (abfd, -16L, SEEK_CUR);
+
+ if (!strncmp (nextname, "__.SYMDEF ", 16))
+ return do_slurp_bsd_armap (abfd);
+
+ if (strncmp (nextname, "/ ", 16))
+ {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ mapdata = snarf_ar_hdr (abfd);
+ if (mapdata == NULL) return false;
+
+ raw_armap = (int *) bfd_zalloc(abfd,mapdata->parsed_size);
+ if (raw_armap == NULL)
+ {
+ bfd_error = no_memory;
+ byebye:
+ bfd_release (abfd, (PTR)mapdata);
+ return false;
+ }
+
+ if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) !=
+ mapdata->parsed_size)
+ {
+ bfd_error = malformed_archive;
+ byebyebye:
+ bfd_release (abfd, (PTR)raw_armap);
+ goto byebye;
+ }
+
+ ardata->symdef_count = bfd_h_get_16(abfd, (PTR)raw_armap);
+
+ if (ardata->symdef_count * sizeof (struct symdef)
+ > mapdata->parsed_size - sizeof (*raw_armap))
+ {
+ /* Probably we're using the wrong byte ordering. */
+ bfd_error = wrong_format;
+ goto byebyebye;
+ }
+
+ ardata->cache = 0;
+
+ stringsize = bfd_h_get_32(abfd, (PTR)(((char*)raw_armap)+2));
+ /* skip sym count and string sz */
+ rbase = (int*)(((char*)raw_armap) + 6);
+ stringbase = (char *) rbase;
+ ardata->symdefs = (carsym *)(((char*) rbase) + stringsize);
+
+ for (;counter < ardata->symdef_count; counter++)
+ {
+ struct symdef *sym = ((struct symdef *) ardata->symdefs) + counter;
+ sym->s.name = bfd_h_get_32(abfd, (PTR)(&(sym->s.string_offset))) + stringbase;
+ sym->file_offset = bfd_h_get_32(abfd, (PTR)( &(sym->file_offset)));
+ }
+
+ 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;
+ /* FIXME, we should provide some way to free raw_ardata when
+ we are done using the strings from it. For now, it seems
+ to be allocated on an obstack anyway... */
+ bfd_has_map (abfd) = true;
+ return true;
+}
+
+/** 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 (decimal). Data General have
+ extended the format by using the prefix // for the special element */
+
+/* Returns false on error, true otherwise */
+boolean
+_bfd_slurp_extended_name_table (abfd)
+ bfd *abfd;
+{
+ char nextname[17];
+ struct areltdata *namedata;
+
+ /* FIXME: Formatting sucks here, and in case of failure of BFD_READ,
+ we probably don't want to return true. */
+ if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) {
+
+ bfd_seek (abfd, (file_ptr) -16, SEEK_CUR);
+
+ if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 &&
+ strncmp (nextname, "// ", 16) != 0)
+ {
+ bfd_ardata (abfd)->extended_names = NULL;
+ return true;
+ }
+
+ namedata = snarf_ar_hdr (abfd);
+ if (namedata == NULL) return false;
+
+ bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size);
+ if (bfd_ardata (abfd)->extended_names == NULL) {
+ bfd_error = no_memory;
+ byebye:
+ bfd_release (abfd, (PTR)namedata);
+ return false;
+ }
+
+ if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1,
+ namedata->parsed_size, abfd) != namedata->parsed_size) {
+ bfd_error = malformed_archive;
+ bfd_release (abfd, (PTR)(bfd_ardata (abfd)->extended_names));
+ bfd_ardata (abfd)->extended_names = NULL;
+ goto byebye;
+ }
+
+ /* Since the archive is supposed to be printable if it contains
+ text, the entries in the list are newline-padded, not null
+ padded. In SVR4-style archives, the names also have a
+ trailing '/'. We'll fix both problems here.. */
+ {
+ char *temp = bfd_ardata (abfd)->extended_names;
+ char *limit = temp + namedata->parsed_size;
+ for (; temp < limit; ++temp)
+ if (*temp == '\n')
+ temp[temp[-1] == '/' ? -1 : 0] = '\0';
+ }
+
+ /* 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;
+
+ /* FIXME, we can't release namedata here because it was allocated
+ below extended_names on the obstack... */
+ /* bfd_release (abfd, namedata); */
+ }
+ return true;
+}
+
+#ifdef VMS
+
+/* Return a copy of the stuff in the filename between any :]> and a
+ semicolon */
+static CONST char *
+DEFUN(normalize,(file),
+ CONST char *file)
+{
+ CONST char *first;
+ CONST char *last;
+ char *copy;
+
+ first = file + strlen(file)-1;
+ last = first+1;
+
+ while (first != file)
+ {
+ if (*first == ';')
+ last = first;
+ if (*first == ':' || *first == ']' ||*first == '>')
+ {
+ first++;
+ break;
+ }
+ first --;
+ }
+
+
+ copy = bfd_xmalloc(last - first + 1);
+ memcpy(copy, first, last-first);
+ copy[last-first] = 0;
+
+ return copy;
+}
+
+#else
+static CONST char *
+DEFUN (normalize, (file),
+ CONST char *file)
+{
+ CONST char * filename = strrchr(file, '/');
+
+ if (filename != (char *)NULL) {
+ filename ++;
+ }
+ else {
+ filename = file;
+ }
+ return filename;
+}
+#endif
+/* 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
+DEFUN (bfd_construct_extended_name_table, (abfd, tabloc, tablen),
+ bfd *abfd AND
+ char **tabloc AND
+ 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 \n */
+ }
+
+ if (total_namelen == 0) return true;
+
+ *tabloc = bfd_zalloc (abfd,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) {
+ CONST 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);
+ strptr[thislen] = '\n';
+ 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, "%-d", (unsigned) (strptr - *tabloc));
+ /* Kinda Kludgy. We should just use the returned value of sprintf
+ but not all implementations get this right */
+ {
+ char *temp = hdr->ar_name +2;
+ for (; temp < hdr->ar_name + maxname; temp++)
+ if (*temp == '\0') *temp = ' ';
+ }
+ strptr += thislen + 1;
+ }
+ }
+
+ return true;
+}
+
+/** 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 *
+DEFUN(bfd_ar_hdr_from_filesystem, (abfd,filename),
+ bfd* abfd AND
+ CONST 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 *) bfd_zalloc(abfd, 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;
+}
+
+/* This is magic required by the "ar" program. Since it's
+ undocumented, it's undocumented. You may think that it would
+ take a strong stomach to write this, and it does, but it takes
+ even a stronger stomach to try to code around such a thing!
+*/
+
+struct ar_hdr *
+DEFUN(bfd_special_undocumented_glue, (abfd, filename),
+ bfd *abfd AND
+ char *filename)
+{
+ struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename);
+ if (ar_elt == NULL)
+ return NULL;
+ return (struct ar_hdr *) ar_elt->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);
+
+ buf->st_size = arch_eltdata (abfd)->parsed_size;
+
+ return 0;
+}
+
+void
+bfd_dont_truncate_arname (abfd, pathname, arhdr)
+ bfd *abfd;
+ CONST char *pathname;
+ char *arhdr;
+{
+ /* FIXME: This interacts unpleasantly with ar's quick-append option.
+ Fortunately ic960 users will never use that option. Fixing this
+ is very hard; fortunately I know how to do it and will do so once
+ intel's release is out the door. */
+
+ struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+ int length;
+ CONST char *filename = normalize(pathname);
+ int maxlen = ar_maxnamelen (abfd);
+
+ length = strlen (filename);
+
+ if (length <= maxlen)
+ memcpy (hdr->ar_name, filename, length);
+
+ if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd);
+ return;
+
+}
+
+void
+bfd_bsd_truncate_arname (abfd, pathname, arhdr)
+ bfd *abfd;
+ CONST char *pathname;
+ char *arhdr;
+{
+ struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+ int length;
+ CONST 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 < maxlen) (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;
+ CONST char *pathname;
+ char *arhdr;
+{
+ struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+ int length;
+ CONST 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);
+}
+
+
+/* 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;
+ int tries;
+
+ /* 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 =
+ (PTR) bfd_ar_hdr_from_filesystem (arch, 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, (file_ptr) 0, SEEK_SET);
+#ifdef GNU960
+ bfd_write (BFD_GNU960_ARMAG(arch), 1, SARMAG, arch);
+#else
+ bfd_write (ARMAG, 1, SARMAG, arch);
+#endif
+
+ if (makemap && hasobjects) {
+
+ if (compute_and_write_armap (arch, elength) != true) {
+ 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 ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
+ bfd_write (etable, 1, elength, arch);
+ if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);
+
+ }
+
+ 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 ((char *)hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
+ syserr:
+ bfd_error = system_call_error;
+ return false;
+ }
+ if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0) goto syserr;
+ while (remaining)
+ {
+ unsigned int amt = DEFAULT_BUFFERSIZE;
+ if (amt > remaining) {
+ amt = remaining;
+ }
+ errno = 0;
+ if (bfd_read (buffer, amt, 1, current) != amt) {
+ if (errno) goto syserr;
+ /* Looks like a truncated archive. */
+ bfd_error = malformed_archive;
+ return false;
+ }
+ if (bfd_write (buffer, amt, 1, arch) != amt) goto syserr;
+ remaining -= amt;
+ }
+ if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch);
+ }
+
+ /* Verify the timestamp in the archive file. If it would
+ not be accepted by the linker, rewrite it until it would be.
+ If anything odd happens, break out and just return.
+ (The Berkeley linker checks the timestamp and refuses to read the
+ table-of-contents if it is >60 seconds less than the file's
+ modified-time. That painful hack requires this painful hack. */
+
+ tries = 1;
+ do {
+ /* FIXME! This kludge is to avoid adding a member to the xvec,
+ while generating a small patch for Adobe. FIXME! The
+ update_armap_timestamp function call should be in the xvec,
+ thus:
+
+ if (bfd_update_armap_timestamp (arch) == true) break;
+ ^
+
+ Instead, we check whether in a BSD archive, and call directly. */
+
+ if (arch->xvec->write_armap != bsd_write_armap)
+ break;
+ if (bsd_update_armap_timestamp(arch) == true) /* FIXME!!! Vector it */
+ break;
+ if (tries > 0)
+ fprintf (stderr,
+ "Warning: writing archive was slow: rewriting timestamp\n");
+ } while (++tries < 6 );
+
+ return true;
+}
+
+/* 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 *) bfd_zalloc (arch,orl_max * sizeof (struct orl));
+ if (map == NULL) {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ /* Drop all the files called __.SYMDEF, we're going to make our
+ own */
+ while (arch->archive_head &&
+ strcmp(arch->archive_head->filename,"__.SYMDEF") == 0)
+ {
+ arch->archive_head = arch->archive_head->next;
+ }
+ /* 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 **) bfd_zalloc (arch,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;
+ asection *sec =
+ syms[src_count]->section;
+
+ if ((flags & BSF_GLOBAL ||
+ flags & BSF_WEAK ||
+ flags & BSF_INDIRECT ||
+ bfd_is_com_section (sec))
+ && (sec != &bfd_und_section)) {
+
+ /* This symbol will go into the archive header */
+ if (orl_count == orl_max)
+ {
+ orl_max *= 2;
+ map = (struct orl *) bfd_realloc (arch, (char *) map,
+ orl_max * sizeof (struct orl));
+ }
+
+ (map[orl_count]).name = (char **) &((syms[src_count])->name);
+ (map[orl_count]).pos = (file_ptr) current;
+ (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))) {
+
+ return false;
+ }
+
+
+ return true;
+}
+
+boolean
+bsd_write_armap (arch, elength, map, orl_count, stridx)
+ bfd *arch;
+ unsigned int elength;
+ struct orl *map;
+ unsigned int orl_count;
+ int stridx;
+{
+ int padit = stridx & 1;
+ unsigned int ranlibsize = orl_count * sizeof (struct ranlib);
+ unsigned int stringsize = stridx + padit;
+ /* Include 8 bytes to store ranlibsize and stringsize in output. */
+ unsigned int mapsize = ranlibsize + stringsize + 8;
+ file_ptr firstreal;
+ bfd *current = arch->archive_head;
+ bfd *last_elt = current; /* last element arch seen */
+ int temp;
+ int count;
+ struct ar_hdr hdr;
+ struct stat statbuf;
+ unsigned int i;
+
+ firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
+
+ stat (arch->filename, &statbuf);
+ memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
+ sprintf (hdr.ar_name, RANLIBMAG);
+ /* Remember the timestamp, to keep it holy. But fudge it a little. */
+ bfd_ardata(arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET;
+ bfd_ardata(arch)->armap_datepos = SARMAG +
+ offsetof(struct ar_hdr, ar_date[0]);
+ sprintf (hdr.ar_date, "%ld", bfd_ardata(arch)->armap_timestamp);
+ sprintf (hdr.ar_uid, "%d", getuid());
+ sprintf (hdr.ar_gid, "%d", getgid());
+ sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+ 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 ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
+ bfd_h_put_32(arch, (bfd_vma) ranlibsize, (PTR)&temp);
+ bfd_write (&temp, 1, sizeof (temp), arch);
+
+ for (count = 0; count < orl_count; count++) {
+ struct symdef outs;
+ struct symdef *outp = &outs;
+
+ if (((bfd *)(map[count]).pos) != last_elt) {
+ do {
+ firstreal += arelt_size (current) + sizeof (struct ar_hdr);
+ firstreal += firstreal % 2;
+ current = current->next;
+ } while (current != (bfd *)(map[count]).pos);
+ } /* if new archive element */
+
+ last_elt = current;
+ bfd_h_put_32(arch, ((map[count]).namidx),(PTR) &outs.s.string_offset);
+ bfd_h_put_32(arch, firstreal,(PTR) &outs.file_offset);
+ bfd_write ((char *)outp, 1, sizeof (outs), arch);
+ }
+
+ /* now write the strings themselves */
+ bfd_h_put_32(arch, stringsize, (PTR)&temp);
+ bfd_write ((PTR)&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;
+}
+
+
+/* At the end of archive file handling, update the timestamp in the
+ file, so the linker will accept it.
+
+ Return true if the timestamp was OK, or an unusual problem happened.
+ Return false if we updated the timestamp. */
+
+static boolean
+bsd_update_armap_timestamp (arch)
+ bfd *arch;
+{
+ struct stat archstat;
+ struct ar_hdr hdr;
+ int i;
+
+ /* Flush writes, get last-write timestamp from file, and compare it
+ to the timestamp IN the file. */
+ bfd_flush (arch);
+ if (bfd_stat (arch, &archstat) == -1) {
+ perror ("Reading archive file mod timestamp");
+ return true; /* Can't read mod time for some reason */
+ }
+ if (archstat.st_mtime <= bfd_ardata(arch)->armap_timestamp)
+ return true; /* OK by the linker's rules */
+
+ /* Update the timestamp. */
+ bfd_ardata(arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET;
+
+ /* Prepare an ASCII version suitable for writing. */
+ memset (hdr.ar_date, 0, sizeof (hdr.ar_date));
+ sprintf (hdr.ar_date, "%ld", bfd_ardata(arch)->armap_timestamp);
+ for (i = 0; i < sizeof (hdr.ar_date); i++)
+ if (hdr.ar_date[i] == '\0')
+ (hdr.ar_date)[i] = ' ';
+
+ /* Write it into the file. */
+ bfd_seek (arch, bfd_ardata(arch)->armap_datepos, SEEK_SET);
+ if (bfd_write (hdr.ar_date, sizeof(hdr.ar_date), 1, arch)
+ != sizeof(hdr.ar_date)) {
+ perror ("Writing updated armap timestamp");
+ return true; /* Some error while writing */
+ }
+
+ return false; /* We updated the timestamp successfully. */
+}
+
+
+/* A coff armap looks like :
+ lARMAG
+ 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, symbol_count, stridx)
+ bfd *arch;
+ unsigned int elength;
+ struct orl *map;
+ unsigned int symbol_count;
+ int stridx;
+{
+ /* The size of the ranlib is the number of exported symbols in the
+ archive * the number of bytes in a int, + an int for the count */
+
+ unsigned int ranlibsize = (symbol_count * 4) + 4;
+ unsigned int stringsize = stridx;
+ unsigned int mapsize = stringsize + ranlibsize;
+ file_ptr archive_member_file_ptr;
+ bfd *current = arch->archive_head;
+ int count;
+ struct ar_hdr hdr;
+ unsigned int i;
+ int padit = mapsize & 1;
+
+ if (padit) mapsize ++;
+
+ /* work out where the first object file will go in the archive */
+ 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", (long)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",(unsigned ) 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 ((PTR)&hdr, 1, sizeof (struct ar_hdr), arch);
+
+ bfd_write_bigendian_4byte_int(arch, symbol_count);
+
+ /* Two passes, first write the file offsets for each symbol -
+ remembering that each offset is on a two byte boundary. */
+
+ /* Write out the file offset for the file associated with each
+ symbol, and remember to keep the offsets padded out. */
+
+ current = arch->archive_head;
+ count = 0;
+ while (current != (bfd *)NULL && count < symbol_count) {
+ /* For each symbol which is used defined in this object, write out
+ the object file's address in the archive */
+
+ while (((bfd *)(map[count]).pos) == current) {
+ bfd_write_bigendian_4byte_int(arch, archive_member_file_ptr);
+ count++;
+ }
+ /* Add size of this archive entry */
+ archive_member_file_ptr += arelt_size (current) + sizeof (struct
+ ar_hdr);
+ /* remember aboout the even alignment */
+ archive_member_file_ptr += archive_member_file_ptr % 2;
+ current = current->next;
+ }
+
+
+
+ /* now write the strings themselves */
+ for (count = 0; count < symbol_count; count++) {
+ bfd_write ((PTR)*((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/gnu/usr.bin/gdb/bfd/archures.c b/gnu/usr.bin/gdb/bfd/archures.c
new file mode 100644
index 000000000000..9697904bd733
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/archures.c
@@ -0,0 +1,731 @@
+/* BFD library support routines for architectures.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Hacked by John Gilmore and Steve Chamberlain of Cygnus Support.
+
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+
+SECTION
+ Architectures
+
+ BFD's idea of an architecture is implimented in
+ <<archures.c>>. BFD keeps one atom in a BFD describing the
+ architecture of the data attached to the BFD; a pointer to a
+ <<bfd_arch_info_type>>.
+
+ Pointers to structures can be requested independently of a bfd
+ so that an architecture's information can be interrogated
+ without access to an open bfd.
+
+ The arch information is provided by each architecture package.
+ The set of default architectures is selected by the #define
+ <<SELECT_ARCHITECTURES>>. This is normally set up in the
+ <<config/target.mt>> file of your choice. If the name is not
+ defined, then all the architectures supported are included.
+
+ When BFD starts up, all the architectures are called with an
+ initialize method. It is up to the architecture back end to
+ insert as many items into the list of architectures as it wants to;
+ generally this would be one for each machine and one for the
+ default case (an item with a machine field of 0).
+*/
+
+/*
+
+SUBSECTION
+ bfd_architecture
+
+DESCRIPTION
+ This enum gives the object file's CPU architecture, in a
+ global sense --- i.e., what processor family does it belong to?
+ There is another field, which indicates what processor within
+ the family is in use. The machine gives a number which
+ distingushes different versions of the architecture,
+ containing for example 2 and 3 for Intel i960 KA and i960 KB,
+ and 68020 and 68030 for Motorola 68020 and 68030.
+
+.enum bfd_architecture
+.{
+. bfd_arch_unknown, {* File arch not known *}
+. bfd_arch_obscure, {* Arch known, not one of these *}
+. bfd_arch_m68k, {* Motorola 68xxx *}
+. bfd_arch_vax, {* DEC Vax *}
+. bfd_arch_i960, {* Intel 960 *}
+. {* The order of the following is important.
+. lower number indicates a machine type that
+. only accepts a subset of the instructions
+. available to machines with higher numbers.
+. The exception is the "ca", which is
+. incompatible with all other machines except
+. "core". *}
+.
+.#define bfd_mach_i960_core 1
+.#define bfd_mach_i960_ka_sa 2
+.#define bfd_mach_i960_kb_sb 3
+.#define bfd_mach_i960_mc 4
+.#define bfd_mach_i960_xa 5
+.#define bfd_mach_i960_ca 6
+.
+. bfd_arch_a29k, {* AMD 29000 *}
+. bfd_arch_sparc, {* SPARC *}
+. bfd_arch_mips, {* MIPS Rxxxx *}
+. bfd_arch_i386, {* Intel 386 *}
+. bfd_arch_we32k, {* AT&T WE32xxx *}
+. bfd_arch_tahoe, {* CCI/Harris Tahoe *}
+. bfd_arch_i860, {* Intel 860 *}
+. bfd_arch_romp, {* IBM ROMP PC/RT *}
+. bfd_arch_alliant, {* Alliant *}
+. bfd_arch_convex, {* Convex *}
+. bfd_arch_m88k, {* Motorola 88xxx *}
+. bfd_arch_pyramid, {* Pyramid Technology *}
+. bfd_arch_h8300, {* Hitachi H8/300 *}
+.#define bfd_mach_h8300 1
+.#define bfd_mach_h8300h 2
+. bfd_arch_rs6000, {* IBM RS/6000 *}
+. bfd_arch_hppa, {* HP PA RISC *}
+. bfd_arch_z8k, {* Zilog Z8000 *}
+.#define bfd_mach_z8001 1
+.#define bfd_mach_z8002 2
+. bfd_arch_h8500, {* Hitachi H8/500 *}
+. bfd_arch_sh, {* Hitachi SH *}
+. bfd_arch_alpha, {* Dec Alpha *}
+. bfd_arch_last
+. };
+
+
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/*
+
+SUBSECTION
+ bfd_arch_info
+
+DESCRIPTION
+ This structure contains information on architectures for use
+ within BFD.
+
+.
+.typedef struct bfd_arch_info
+.{
+. int bits_per_word;
+. int bits_per_address;
+. int bits_per_byte;
+. enum bfd_architecture arch;
+. long mach;
+. char *arch_name;
+. CONST char *printable_name;
+. unsigned int section_align_power;
+. {* true if this is the default machine for the architecture *}
+. boolean the_default;
+. CONST struct bfd_arch_info * (*compatible)
+. PARAMS ((CONST struct bfd_arch_info *a,
+. CONST struct bfd_arch_info *b));
+.
+. boolean (*scan) PARAMS ((CONST struct bfd_arch_info *, CONST char *));
+. {* How to disassemble an instruction, producing a printable
+. representation on a specified stdio stream. This isn't
+. defined for most processors at present, because of the size
+. of the additional tables it would drag in, and because gdb
+. wants to use a different interface. *}
+. unsigned int (*disassemble) PARAMS ((bfd_vma addr, CONST char *data,
+. PTR stream));
+.
+. struct bfd_arch_info *next;
+.} bfd_arch_info_type;
+*/
+
+bfd_arch_info_type *bfd_arch_info_list;
+
+
+/*
+FUNCTION
+ bfd_printable_name
+
+SYNOPSIS
+ CONST char *bfd_printable_name(bfd *abfd);
+
+DESCRIPTION
+ Return a printable string representing the architecture and machine
+ from the pointer to the arch info structure
+
+*/
+
+CONST char *
+DEFUN(bfd_printable_name, (abfd),
+ bfd *abfd)
+{
+ return abfd->arch_info->printable_name;
+}
+
+
+
+/*
+FUNCTION
+ bfd_scan_arch
+
+SYNOPSIS
+ bfd_arch_info_type *bfd_scan_arch(CONST char *);
+
+DESCRIPTION
+ This routine is provided with a string and tries to work out
+ if bfd supports any cpu which could be described with the name
+ provided. The routine returns a pointer to an arch_info
+ structure if a machine is found, otherwise NULL.
+
+*/
+
+bfd_arch_info_type *
+DEFUN(bfd_scan_arch,(string),
+ CONST char *string)
+{
+ struct bfd_arch_info *ap;
+
+ /* Look through all the installed architectures */
+ for (ap = bfd_arch_info_list;
+ ap != (bfd_arch_info_type *)NULL;
+ ap = ap->next) {
+
+ if (ap->scan(ap, string))
+ return ap;
+ }
+ return (bfd_arch_info_type *)NULL;
+}
+
+
+
+/*
+FUNCTION
+ bfd_arch_get_compatible
+
+SYNOPSIS
+ CONST bfd_arch_info_type *bfd_arch_get_compatible(
+ CONST bfd *abfd,
+ CONST bfd *bbfd);
+
+DESCRIPTION
+ This routine is used to determine whether two BFDs'
+ architectures and achine types are compatible. It calculates
+ the lowest common denominator between the two architectures
+ and machine types implied by the BFDs and returns a pointer to
+ an arch_info structure describing the compatible machine.
+*/
+
+CONST bfd_arch_info_type *
+DEFUN(bfd_arch_get_compatible,(abfd, bbfd),
+CONST bfd *abfd AND
+CONST bfd *bbfd)
+
+{
+ return abfd->arch_info->compatible(abfd->arch_info,bbfd->arch_info);
+}
+
+
+/*
+INTERNAL_DEFINITION
+ bfd_default_arch_struct
+
+DESCRIPTION
+ The <<bfd_default_arch_struct>> is an item of
+ <<bfd_arch_info_type>> which has been initialized to a fairly
+ generic state. A BFD starts life by pointing to this
+ structure, until the correct back end has determined the real
+ architecture of the file.
+
+.extern bfd_arch_info_type bfd_default_arch_struct;
+
+*/
+
+bfd_arch_info_type bfd_default_arch_struct =
+{
+ 32,32,8,bfd_arch_unknown,0,"unknown","unknown",2,true,
+ bfd_default_compatible,
+ bfd_default_scan,
+ 0,
+};
+
+/*
+FUNCTION
+ bfd_set_arch_info
+
+SYNOPSIS
+ void bfd_set_arch_info(bfd *, bfd_arch_info_type *);
+
+*/
+
+void DEFUN(bfd_set_arch_info,(abfd, arg),
+bfd *abfd AND
+bfd_arch_info_type *arg)
+{
+ abfd->arch_info = arg;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_default_set_arch_mach
+
+SYNOPSIS
+ boolean bfd_default_set_arch_mach(bfd *abfd,
+ enum bfd_architecture arch,
+ unsigned long mach);
+
+DESCRIPTION
+ Set the architecture and machine type in a bfd. This finds the
+ correct pointer to structure and inserts it into the arch_info
+ pointer.
+*/
+
+boolean DEFUN(bfd_default_set_arch_mach,(abfd, arch, mach),
+ bfd *abfd AND
+ enum bfd_architecture arch AND
+ unsigned long mach)
+{
+ static struct bfd_arch_info *old_ptr = &bfd_default_arch_struct;
+ boolean found = false;
+ /* run through the table to find the one we want, we keep a little
+ cache to speed things up */
+ if (old_ptr == 0 || arch != old_ptr->arch || mach != old_ptr->mach) {
+ bfd_arch_info_type *ptr;
+ old_ptr = (bfd_arch_info_type *)NULL;
+ for (ptr = bfd_arch_info_list;
+ ptr != (bfd_arch_info_type *)NULL;
+ ptr= ptr->next) {
+ if (ptr->arch == arch &&
+ ((ptr->mach == mach) || (ptr->the_default && mach == 0))) {
+ old_ptr = ptr;
+ found = true;
+ break;
+ }
+ }
+ if (found==false) {
+ /*looked for it and it wasn't there, so put in the default */
+ old_ptr = &bfd_default_arch_struct;
+ bfd_error = bad_value;
+ }
+ }
+ else {
+ /* it was in the cache */
+ found = true;
+ }
+
+ abfd->arch_info = old_ptr;
+
+ return found;
+}
+
+
+
+
+
+/*
+FUNCTION
+ bfd_get_arch
+
+SYNOPSIS
+ enum bfd_architecture bfd_get_arch(bfd *abfd);
+
+DESCRIPTION
+ Returns the enumerated type which describes the supplied bfd's
+ architecture
+
+*/
+
+enum bfd_architecture DEFUN(bfd_get_arch, (abfd), bfd *abfd)
+{
+ return abfd->arch_info->arch;
+}
+
+/*
+FUNCTION
+ bfd_get_mach
+
+SYNOPSIS
+ unsigned long bfd_get_mach(bfd *abfd);
+
+DESCRIPTION
+ Returns the long type which describes the supplied bfd's
+ machine
+*/
+
+unsigned long
+DEFUN(bfd_get_mach, (abfd), bfd *abfd)
+{
+ return abfd->arch_info->mach;
+}
+
+/*
+FUNCTION
+ bfd_arch_bits_per_byte
+
+SYNOPSIS
+ unsigned int bfd_arch_bits_per_byte(bfd *abfd);
+
+DESCRIPTION
+ Returns the number of bits in one of the architectures bytes
+
+*/
+
+unsigned int DEFUN(bfd_arch_bits_per_byte, (abfd), bfd *abfd)
+ {
+ return abfd->arch_info->bits_per_byte;
+ }
+
+/*
+FUNCTION
+ bfd_arch_bits_per_address
+
+SYNOPSIS
+ unsigned int bfd_arch_bits_per_address(bfd *abfd);
+
+DESCRIPTION
+ Returns the number of bits in one of the architectures addresses
+*/
+
+unsigned int DEFUN(bfd_arch_bits_per_address, (abfd), bfd *abfd)
+ {
+ return abfd->arch_info->bits_per_address;
+ }
+
+
+extern void bfd_a29k_arch PARAMS ((void));
+extern void bfd_alpha_arch PARAMS ((void));
+extern void bfd_h8300_arch PARAMS ((void));
+extern void bfd_h8500_arch PARAMS ((void));
+extern void bfd_hppa_arch PARAMS ((void));
+extern void bfd_i386_arch PARAMS ((void));
+extern void bfd_i960_arch PARAMS ((void));
+extern void bfd_m68k_arch PARAMS ((void));
+extern void bfd_m88k_arch PARAMS ((void));
+extern void bfd_mips_arch PARAMS ((void));
+extern void bfd_rs6000_arch PARAMS ((void));
+extern void bfd_sh_arch PARAMS ((void));
+extern void bfd_sparc_arch PARAMS ((void));
+extern void bfd_vax_arch PARAMS ((void));
+extern void bfd_we32k_arch PARAMS ((void));
+extern void bfd_z8k_arch PARAMS ((void));
+
+static void (*archures_init_table[]) PARAMS ((void)) =
+{
+#ifdef SELECT_ARCHITECTURES
+ SELECT_ARCHITECTURES,
+#else
+ bfd_a29k_arch,
+ bfd_alpha_arch,
+ bfd_h8300_arch,
+ bfd_h8500_arch,
+ bfd_hppa_arch,
+ bfd_i386_arch,
+ bfd_i960_arch,
+ bfd_m68k_arch,
+ bfd_m88k_arch,
+ bfd_mips_arch,
+ bfd_rs6000_arch,
+ bfd_sh_arch,
+ bfd_sparc_arch,
+ bfd_vax_arch,
+ bfd_we32k_arch,
+ bfd_z8k_arch,
+#endif
+ 0
+ };
+
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_arch_init
+
+SYNOPSIS
+ void bfd_arch_init(void);
+
+DESCRIPTION
+ This routine initializes the architecture dispatch table by
+ calling all installed architecture packages and getting them
+ to poke around.
+*/
+
+void
+DEFUN_VOID(bfd_arch_init)
+{
+ void (**ptable) PARAMS ((void));
+ for (ptable = archures_init_table;
+ *ptable ;
+ ptable++)
+ {
+ (*ptable)();
+ }
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_arch_linkin
+
+SYNOPSIS
+ void bfd_arch_linkin(bfd_arch_info_type *);
+
+DESCRIPTION
+ Link the provided arch info structure into the list
+*/
+
+void DEFUN(bfd_arch_linkin,(ptr),
+ bfd_arch_info_type *ptr)
+{
+ ptr->next = bfd_arch_info_list;
+ bfd_arch_info_list = ptr;
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_default_compatible
+
+SYNOPSIS
+ CONST bfd_arch_info_type *bfd_default_compatible
+ (CONST bfd_arch_info_type *a,
+ CONST bfd_arch_info_type *b);
+
+DESCRIPTION
+ The default function for testing for compatibility.
+*/
+
+CONST bfd_arch_info_type *
+DEFUN(bfd_default_compatible,(a,b),
+ CONST bfd_arch_info_type *a AND
+ CONST bfd_arch_info_type *b)
+{
+ if(a->arch != b->arch) return NULL;
+
+ if (a->mach > b->mach) {
+ return a;
+ }
+ if (b->mach > a->mach) {
+ return b;
+ }
+ return a;
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_default_scan
+
+SYNOPSIS
+ boolean bfd_default_scan(CONST struct bfd_arch_info *, CONST char *);
+
+DESCRIPTION
+ The default function for working out whether this is an
+ architecture hit and a machine hit.
+*/
+
+boolean
+DEFUN(bfd_default_scan,(info, string),
+CONST struct bfd_arch_info *info AND
+CONST char *string)
+{
+ CONST char *ptr_src;
+ CONST char *ptr_tst;
+ unsigned long number;
+ enum bfd_architecture arch;
+ /* First test for an exact match */
+ if (strcmp(string, info->printable_name) == 0) return true;
+
+ /* See how much of the supplied string matches with the
+ architecture, eg the string m68k:68020 would match the 68k entry
+ up to the :, then we get left with the machine number */
+
+ for (ptr_src = string,
+ ptr_tst = info->arch_name;
+ *ptr_src && *ptr_tst;
+ ptr_src++,
+ ptr_tst++)
+ {
+ if (*ptr_src != *ptr_tst) break;
+ }
+
+ /* Chewed up as much of the architecture as will match, skip any
+ colons */
+ if (*ptr_src == ':') ptr_src++;
+
+ if (*ptr_src == 0) {
+ /* nothing more, then only keep this one if it is the default
+ machine for this architecture */
+ return info->the_default;
+ }
+ number = 0;
+ while (isdigit(*ptr_src)) {
+ number = number * 10 + *ptr_src - '0';
+ ptr_src++;
+ }
+
+ switch (number)
+ {
+ case 300:
+ arch = bfd_arch_h8300;
+ break;
+
+ case 500:
+ arch = bfd_arch_h8500;
+ break;
+
+ case 68010:
+ case 68020:
+ case 68030:
+ case 68040:
+ case 68332:
+ case 68050:
+ case 68000:
+ arch = bfd_arch_m68k;
+ break;
+ case 386:
+ case 80386:
+ case 486:
+ case 80486:
+ arch = bfd_arch_i386;
+ break;
+ case 29000:
+ arch = bfd_arch_a29k;
+ break;
+
+ case 8000:
+ arch = bfd_arch_z8k;
+ break;
+
+ case 32000:
+ arch = bfd_arch_we32k;
+ break;
+
+ case 860:
+ case 80860:
+ arch = bfd_arch_i860;
+ break;
+ case 960:
+ case 80960:
+ arch = bfd_arch_i960;
+ break;
+
+ case 2000:
+ case 3000:
+ case 4000:
+ case 4400:
+ arch = bfd_arch_mips;
+ break;
+
+ case 6000:
+ arch = bfd_arch_rs6000;
+ break;
+
+ default:
+ return false;
+ }
+ if (arch != info->arch)
+ return false;
+
+ if (number != info->mach)
+ return false;
+
+ return true;
+}
+
+
+
+
+/*
+FUNCTION
+ bfd_get_arch_info
+
+
+SYNOPSIS
+ bfd_arch_info_type * bfd_get_arch_info(bfd *);
+
+*/
+
+bfd_arch_info_type *
+DEFUN(bfd_get_arch_info,(abfd),
+bfd *abfd)
+{
+ return abfd->arch_info;
+}
+
+
+/*
+FUNCTION
+ bfd_lookup_arch
+
+SYNOPSIS
+ bfd_arch_info_type *bfd_lookup_arch
+ (enum bfd_architecture
+ arch,
+ long machine);
+
+DESCRIPTION
+ Look for the architecure info struct which matches the
+ arguments given. A machine of 0 will match the
+ machine/architecture structure which marks itself as the
+ default.
+*/
+
+bfd_arch_info_type *
+DEFUN(bfd_lookup_arch,(arch, machine),
+enum bfd_architecture arch AND
+long machine)
+{
+ bfd_arch_info_type *ap;
+ bfd_check_init();
+ for (ap = bfd_arch_info_list;
+ ap != (bfd_arch_info_type *)NULL;
+ ap = ap->next) {
+ if (ap->arch == arch &&
+ ((ap->mach == machine)
+ || (ap->the_default && machine == 0))) {
+ return ap;
+ }
+ }
+ return (bfd_arch_info_type *)NULL;
+}
+
+
+
+/*
+FUNCTION
+ bfd_printable_arch_mach
+
+SYNOPSIS
+ CONST char * bfd_printable_arch_mach
+ (enum bfd_architecture arch, unsigned long machine);
+
+DESCRIPTION
+ Return a printable string representing the architecture and
+ machine type.
+
+ NB. The use of this routine is depreciated.
+*/
+
+CONST char *
+DEFUN(bfd_printable_arch_mach,(arch, machine),
+ enum bfd_architecture arch AND
+ unsigned long machine)
+{
+ bfd_arch_info_type *ap = bfd_lookup_arch(arch, machine);
+ if(ap) return ap->printable_name;
+ return "UNKNOWN!";
+}
diff --git a/gnu/usr.bin/gdb/bfd/bfd.c b/gnu/usr.bin/gdb/bfd/bfd.c
new file mode 100644
index 000000000000..a994cd170a00
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/bfd.c
@@ -0,0 +1,733 @@
+/* Generic BFD library interface and support routines.
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ <<typedef bfd>>
+
+ A BFD is has type <<bfd>>; objects of this type are the
+ cornerstone of any application using <<libbfd>>. References
+ though the BFD and to data in the BFD give the entire BFD
+ functionality.
+
+ Here is the struct used to define the type <<bfd>>. This
+ contains the major data about the file, and contains pointers
+ to the rest of the data.
+
+CODE_FRAGMENT
+.
+.struct _bfd
+.{
+. {* The filename the application opened the BFD with. *}
+. CONST char *filename;
+.
+. {* A pointer to the target jump table. *}
+. struct bfd_target *xvec;
+.
+. {* To avoid dragging too many header files into every file that
+. includes `<<bfd.h>>', IOSTREAM has been declared as a "char
+. *", and MTIME as a "long". Their correct types, to which they
+. are cast when used, are "FILE *" and "time_t". The iostream
+. is the result of an fopen on the filename. *}
+. char *iostream;
+.
+. {* Is the file being cached *}
+.
+. boolean cacheable;
+.
+. {* Marks whether there was a default target specified when the
+. BFD was opened. This is used to select what matching algorithm
+. to use to chose the back end. *}
+.
+. boolean target_defaulted;
+.
+. {* The caching routines use these to maintain a
+. least-recently-used list of BFDs *}
+.
+. struct _bfd *lru_prev, *lru_next;
+.
+. {* When a file is closed by the caching routines, BFD retains
+. state information on the file here:
+. *}
+.
+. file_ptr where;
+.
+. {* and here:*}
+.
+. boolean opened_once;
+.
+. {* Set if we have a locally maintained mtime value, rather than
+. getting it from the file each time: *}
+.
+. boolean mtime_set;
+.
+. {* File modified time, if mtime_set is true: *}
+.
+. long mtime;
+.
+. {* Reserved for an unimplemented file locking extension.*}
+.
+. int ifd;
+.
+. {* The format which belongs to the BFD.*}
+.
+. bfd_format format;
+.
+. {* The direction the BFD was opened with*}
+.
+. enum bfd_direction {no_direction = 0,
+. read_direction = 1,
+. write_direction = 2,
+. both_direction = 3} direction;
+.
+. {* Format_specific flags*}
+.
+. flagword flags;
+.
+. {* Currently my_archive is tested before adding origin to
+. anything. I believe that this can become always an add of
+. origin, with origin set to 0 for non archive files. *}
+.
+. file_ptr origin;
+.
+. {* Remember when output has begun, to stop strange things
+. happening. *}
+. boolean output_has_begun;
+.
+. {* Pointer to linked list of sections*}
+. struct sec *sections;
+.
+. {* The number of sections *}
+. unsigned int section_count;
+.
+. {* Stuff only useful for object files:
+. The start address. *}
+. bfd_vma start_address;
+.
+. {* Used for input and output*}
+. unsigned int symcount;
+.
+. {* Symbol table for output BFD*}
+. struct symbol_cache_entry **outsymbols;
+.
+. {* Pointer to structure which contains architecture information*}
+. struct bfd_arch_info *arch_info;
+.
+. {* Stuff only useful for archives:*}
+. PTR arelt_data;
+. struct _bfd *my_archive;
+. struct _bfd *next;
+. struct _bfd *archive_head;
+. boolean has_armap;
+.
+. {* Used by the back end to hold private data. *}
+.
+. union
+. {
+. struct aout_data_struct *aout_data;
+. struct artdata *aout_ar_data;
+. struct _oasys_data *oasys_obj_data;
+. struct _oasys_ar_data *oasys_ar_data;
+. struct coff_tdata *coff_obj_data;
+. struct ecoff_tdata *ecoff_obj_data;
+. struct ieee_data_struct *ieee_data;
+. struct ieee_ar_data_struct *ieee_ar_data;
+. struct srec_data_struct *srec_data;
+. struct tekhex_data_struct *tekhex_data;
+. struct elf_obj_tdata *elf_obj_data;
+. struct nlm_obj_tdata *nlm_obj_data;
+. struct bout_data_struct *bout_data;
+. struct sun_core_struct *sun_core_data;
+. struct trad_core_struct *trad_core_data;
+. struct hppa_data_struct *hppa_data;
+. struct hpux_core_struct *hpux_core_data;
+. struct sgi_core_struct *sgi_core_data;
+. struct lynx_core_struct *lynx_core_data;
+. struct osf_core_struct *osf_core_data;
+. PTR any;
+. } tdata;
+.
+. {* Used by the application to hold private data*}
+. PTR usrdata;
+.
+. {* Where all the allocated stuff under this BFD goes *}
+. struct obstack memory;
+.
+. {* Is this really needed in addition to usrdata? *}
+. asymbol **ld_symbols;
+.};
+.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "libcoff.h"
+#include "libecoff.h"
+#undef obj_symbols
+#include "libelf.h"
+
+#undef strerror
+extern char *strerror();
+
+/** 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;
+
+CONST char *CONST 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",
+ "Nonrepresentable section on output",
+ "Symbol needs debug section which does not exist",
+ "Bad value",
+ "File truncated",
+ "#<Invalid error code>"
+ };
+
+static
+void
+DEFUN(bfd_nonrepresentable_section,(abfd, name),
+ CONST bfd * CONST abfd AND
+ CONST char * CONST name)
+{
+ fprintf(stderr,
+ "bfd error writing file %s, format %s can't represent section %s\n",
+ abfd->filename,
+ abfd->xvec->name,
+ name);
+ exit(1);
+}
+
+/*ARGSUSED*/
+static
+void
+DEFUN(bfd_undefined_symbol,(relent, seclet),
+ CONST arelent *relent AND
+ CONST struct bfd_seclet *seclet)
+{
+ asymbol *symbol = *(relent->sym_ptr_ptr);
+ fprintf(stderr, "bfd error relocating, symbol %s is undefined\n",
+ symbol->name);
+ exit(1);
+}
+/*ARGSUSED*/
+static
+void
+DEFUN(bfd_reloc_value_truncated,(relent, seclet),
+ CONST arelent *relent AND
+ struct bfd_seclet *seclet)
+{
+ fprintf(stderr, "bfd error relocating, value truncated\n");
+ exit(1);
+}
+/*ARGSUSED*/
+static
+void
+DEFUN(bfd_reloc_is_dangerous,(relent, seclet),
+ CONST arelent *relent AND
+ CONST struct bfd_seclet *seclet)
+{
+ fprintf(stderr, "bfd error relocating, dangerous\n");
+ exit(1);
+}
+
+bfd_error_vector_type bfd_error_vector =
+ {
+ bfd_nonrepresentable_section ,
+ bfd_undefined_symbol,
+ bfd_reloc_value_truncated,
+ bfd_reloc_is_dangerous,
+ };
+
+
+CONST char *
+bfd_errmsg (error_tag)
+ bfd_ec error_tag;
+{
+#ifndef errno
+ extern int errno;
+#endif
+ 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
+DEFUN (bfd_default_error_trap, (error_tag),
+ bfd_ec error_tag)
+{
+ fprintf(stderr, "bfd assert fail (%s)\n", bfd_errmsg(error_tag));
+}
+
+void (*bfd_error_trap) PARAMS ((bfd_ec)) = bfd_default_error_trap;
+void (*bfd_error_nonrepresentabltrap) PARAMS ((bfd_ec)) = bfd_default_error_trap;
+
+void
+DEFUN(bfd_perror,(message),
+ CONST char *message)
+{
+ if (bfd_error == system_call_error)
+ perror((char *)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));
+ }
+}
+
+
+/** Symbols */
+
+
+/*
+FUNCTION
+ bfd_get_reloc_upper_bound
+
+SYNOPSIS
+ unsigned int bfd_get_reloc_upper_bound(bfd *abfd, asection *sect);
+
+DESCRIPTION
+ This function return the number of bytes required to store the
+ relocation information associated with section <<sect>>
+ attached to bfd <<abfd>>
+
+*/
+
+
+unsigned int
+DEFUN(bfd_get_reloc_upper_bound,(abfd, asect),
+ bfd *abfd AND
+ sec_ptr asect)
+{
+ if (abfd->format != bfd_object) {
+ bfd_error = invalid_operation;
+ return 0;
+ }
+
+ return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect));
+}
+
+/*
+FUNCTION
+ bfd_canonicalize_reloc
+
+SYNOPSIS
+ unsigned int bfd_canonicalize_reloc
+ (bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms);
+
+DESCRIPTION
+ This function calls the back end associated with the open
+ <<abfd>> and translates the external form of the relocation
+ information attached to <<sec>> into the internal canonical
+ form. The table is placed into memory at <<loc>>, which has
+ been preallocated, usually by a call to
+ <<bfd_get_reloc_upper_bound>>.
+
+ The <<syms>> table is also needed for horrible internal magic
+ reasons.
+
+
+*/
+unsigned int
+DEFUN(bfd_canonicalize_reloc,(abfd, asect, location, symbols),
+ bfd *abfd AND
+ sec_ptr asect AND
+ arelent **location AND
+ asymbol **symbols)
+{
+ if (abfd->format != bfd_object) {
+ bfd_error = invalid_operation;
+ return 0;
+ }
+ return BFD_SEND (abfd, _bfd_canonicalize_reloc,
+ (abfd, asect, location, symbols));
+ }
+
+
+/*
+FUNCTION
+ bfd_set_file_flags
+
+SYNOPSIS
+ boolean bfd_set_file_flags(bfd *abfd, flagword flags);
+
+DESCRIPTION
+ This function attempts to set the flag word in the referenced
+ BFD structure to the value supplied.
+
+ Possible errors are:
+ o wrong_format - The target bfd was not of object format.
+ o invalid_operation - The target bfd was open for reading.
+ o invalid_operation -
+ The flag word contained a bit which was not applicable to the
+ type of file. eg, an attempt was made to set the D_PAGED bit
+ on a bfd format which does not support demand paging
+
+*/
+
+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;
+ }
+
+ bfd_get_file_flags (abfd) = flags;
+ if ((flags & bfd_applicable_file_flags (abfd)) != flags) {
+ bfd_error = invalid_operation;
+ return false;
+ }
+
+return true;
+}
+
+/*
+FUNCTION
+ bfd_set_reloc
+
+SYNOPSIS
+ void bfd_set_reloc
+ (bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+
+DESCRIPTION
+ This function sets the relocation pointer and count within a
+ section to the supplied values.
+
+*/
+/*ARGSUSED*/
+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;
+}
+
+void
+bfd_assert(file, line)
+char *file;
+int line;
+{
+ fprintf(stderr, "bfd assertion fail %s:%d\n",file,line);
+}
+
+
+/*
+FUNCTION
+ bfd_set_start_address
+
+DESCRIPTION
+ Marks the entry point of an output BFD.
+
+RETURNS
+ Returns <<true>> on success, <<false>> otherwise.
+
+SYNOPSIS
+ boolean bfd_set_start_address(bfd *, bfd_vma);
+*/
+
+boolean
+bfd_set_start_address(abfd, vma)
+bfd *abfd;
+bfd_vma vma;
+{
+ abfd->start_address = vma;
+ return true;
+}
+
+
+/*
+FUNCTION
+ The bfd_get_mtime function
+
+SYNOPSIS
+ long bfd_get_mtime(bfd *);
+
+DESCRIPTION
+ Return file modification time (as read from file system, or
+ from archive header for archive members).
+
+*/
+
+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 = buf.st_mtime; /* Save value in case anyone wants it */
+ return buf.st_mtime;
+}
+
+/*
+FUNCTION
+ The bfd_get_size function
+
+SYNOPSIS
+ long bfd_get_size(bfd *);
+
+DESCRIPTION
+ Return file size (as read from file system) for the file
+ associated with a bfd.
+
+ Note that the initial motivation for, and use of, this routine is not
+ so we can get the exact size of the object the bfd applies to, since
+ that might not be generally possible (archive members for example?).
+ Although it would be ideal if someone could eventually modify
+ it so that such results were guaranteed.
+
+ Instead, we want to ask questions like "is this NNN byte sized
+ object I'm about to try read from file offset YYY reasonable?"
+ As as example of where we might want to do this, some object formats
+ use string tables for which the first sizeof(long) bytes of the table
+ contain the size of the table itself, including the size bytes.
+ If an application tries to read what it thinks is one of these
+ string tables, without some way to validate the size, and for
+ some reason the size is wrong (byte swapping error, wrong location
+ for the string table, etc), the only clue is likely to be a read
+ error when it tries to read the table, or a "virtual memory
+ exhausted" error when it tries to allocated 15 bazillon bytes
+ of space for the 15 bazillon byte table it is about to read.
+ This function at least allows us to answer the quesion, "is the
+ size reasonable?".
+*/
+
+long
+bfd_get_size (abfd)
+ bfd *abfd;
+{
+ FILE *fp;
+ struct stat buf;
+
+ fp = bfd_cache_lookup (abfd);
+ if (0 != fstat (fileno (fp), &buf))
+ return 0;
+
+ return buf.st_size;
+}
+
+/*
+FUNCTION
+ The bfd_get_gp_size function
+
+SYNOPSIS
+ int bfd_get_gp_size(bfd *);
+
+DESCRIPTION
+ Get the maximum size of objects to be optimized using the GP
+ register under MIPS ECOFF. This is typically set by the -G
+ argument to the compiler, assembler or linker.
+*/
+
+int
+bfd_get_gp_size (abfd)
+ bfd *abfd;
+{
+ if (abfd->xvec->flavour == bfd_target_ecoff_flavour)
+ return ecoff_data (abfd)->gp_size;
+ return 0;
+}
+
+/*
+FUNCTION
+ The bfd_set_gp_size function
+
+SYNOPSIS
+ void bfd_set_gp_size(bfd *, int);
+
+DESCRIPTION
+ Set the maximum size of objects to be optimized using the GP
+ register under ECOFF or MIPS ELF. This is typically set by
+ the -G argument to the compiler, assembler or linker.
+*/
+
+void
+bfd_set_gp_size (abfd, i)
+ bfd *abfd;
+ int i;
+{
+ if (abfd->xvec->flavour == bfd_target_ecoff_flavour)
+ ecoff_data (abfd)->gp_size = i;
+ else if (abfd->xvec->flavour == bfd_target_elf_flavour)
+ elf_gp_size (abfd) = i;
+}
+
+/*
+FUNCTION
+ bfd_scan_vma
+
+DESCRIPTION
+ Converts, like strtoul, a numerical expression as a
+ string into a bfd_vma integer, and returns that integer.
+ (Though without as many bells and whistles as strtoul.)
+ The expression is assumed to be unsigned (i.e. positive).
+ If given a base, it is used as the base for conversion.
+ A base of 0 causes the function to interpret the string
+ in hex if a leading "0x" or "0X" is found, otherwise
+ in octal if a leading zero is found, otherwise in decimal.
+
+ Overflow is not detected.
+
+SYNOPSIS
+ bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base);
+*/
+
+bfd_vma
+DEFUN(bfd_scan_vma,(string, end, base),
+ CONST char *string AND
+ CONST char **end AND
+ int base)
+{
+ bfd_vma value;
+ int digit;
+
+ /* Let the host do it if possible. */
+ if (sizeof(bfd_vma) <= sizeof(unsigned long))
+ return (bfd_vma) strtoul (string, 0, base);
+
+ /* A negative base makes no sense, and we only need to go as high as hex. */
+ if ((base < 0) || (base > 16))
+ return (bfd_vma) 0;
+
+ if (base == 0)
+ {
+ if (string[0] == '0')
+ {
+ if ((string[1] == 'x') || (string[1] == 'X'))
+ base = 16;
+ /* XXX should we also allow "0b" or "0B" to set base to 2? */
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+ if ((base == 16) &&
+ (string[0] == '0') && ((string[1] == 'x') || (string[1] == 'X')))
+ string += 2;
+ /* XXX should we also skip over "0b" or "0B" if base is 2? */
+
+/* Speed could be improved with a table like hex_value[] in gas. */
+#define HEX_VALUE(c) \
+ (isxdigit(c) ? \
+ (isdigit(c) ? \
+ (c - '0') : \
+ (10 + c - (islower(c) ? 'a' : 'A'))) : \
+ 42)
+
+ for (value = 0; (digit = HEX_VALUE(*string)) < base; string++)
+ {
+ value = value * base + digit;
+ }
+
+ if (end)
+ *end = string;
+
+ return value;
+}
+
+/*
+FUNCTION
+ stuff
+
+DESCRIPTION
+ stuff which should be documented
+
+.#define bfd_sizeof_headers(abfd, reloc) \
+. BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+.
+.#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+. BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+.
+. {* Do these three do anything useful at all, for any back end? *}
+.#define bfd_debug_info_start(abfd) \
+. BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+.
+.#define bfd_debug_info_end(abfd) \
+. BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+.
+.#define bfd_debug_info_accumulate(abfd, section) \
+. BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+.
+.
+.#define bfd_stat_arch_elt(abfd, stat) \
+. BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+.
+.#define bfd_set_arch_mach(abfd, arch, mach)\
+. BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+.
+.#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \
+. BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable))
+.
+.#define bfd_relax_section(abfd, section, symbols) \
+. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols))
+.
+.#define bfd_seclet_link(abfd, data, relocateable) \
+. BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable))
+
+*/
diff --git a/gnu/usr.bin/gdb/bfd/bfd.h b/gnu/usr.bin/gdb/bfd/bfd.h
new file mode 100644
index 000000000000..fbe0f0f36ba4
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/bfd.h
@@ -0,0 +1,1803 @@
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+** NOTE: bfd.h and bfd-in2.h are GENERATED files. Don't change them;
+** instead, change bfd-in.h or the other BFD source files processed to
+** generate these files.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* bfd.h -- The only header file required by users of the bfd library
+
+The bfd.h file is generated from bfd-in.h and various .c files; if you
+change it, your changes will probably be lost.
+
+All the prototypes and definitions following the comment "THE FOLLOWING
+IS EXTRACTED FROM THE SOURCE" are extracted from the source files for
+BFD. If you change it, someone oneday will extract it from the source
+again, and your changes will be lost. To save yourself from this bind,
+change the definitions in the source in the bfd directory. Type "make
+docs" and then "make headers" in that directory, and magically this file
+will change to reflect your changes.
+
+If you don't have the tools to perform the extraction, then you are
+safe from someone on your system trampling over your header files.
+You should still maintain the equivalence between the source and this
+file though; every change you make to the .c file should be reflected
+here. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#include "ansidecl.h"
+#include "obstack.h"
+
+#define BFD_VERSION "2.2"
+
+#define BFD_ARCH_SIZE 32
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* 64-bit type definition (if any) from bfd's sysdep.h goes here */
+
+
+/* forward declaration */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+typedef enum bfd_boolean {false, true} boolean;
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef long int file_ptr;
+
+/* Support for different sizes of target format ints and addresses. If the
+ host implements 64-bit values, it defines HOST_64_BIT to be the appropriate
+ type. Otherwise, this code will fall back on gcc's "long long" type if gcc
+ is being used. HOST_64_BIT must be defined in such a way as to be a valid
+ type name by itself or with "unsigned" prefixed. It should be a signed
+ type by itself.
+
+ If neither is the case, then compilation will fail if 64-bit targets are
+ requested. If you don't request any 64-bit targets, you should be safe. */
+
+#ifdef BFD64
+
+#if defined (__GNUC__) && !defined (HOST_64_BIT)
+#define HOST_64_BIT long long
+typedef HOST_64_BIT int64_type;
+typedef unsigned HOST_64_BIT uint64_type;
+#endif
+
+#if !defined (uint64_type) && defined (__GNUC__)
+#define uint64_type unsigned long long
+#define int64_type long long
+#define uint64_typeLOW(x) (unsigned long)(((x) & 0xffffffff))
+#define uint64_typeHIGH(x) (unsigned long)(((x) >> 32) & 0xffffffff)
+#endif
+
+typedef unsigned HOST_64_BIT bfd_vma;
+typedef HOST_64_BIT bfd_signed_vma;
+typedef unsigned HOST_64_BIT bfd_size_type;
+typedef unsigned HOST_64_BIT symvalue;
+#define fprintf_vma(s,x) \
+ fprintf(s,"%08x%08x", uint64_typeHIGH(x), uint64_typeLOW(x))
+#define sprintf_vma(s,x) \
+ sprintf(s,"%08x%08x", uint64_typeHIGH(x), uint64_typeLOW(x))
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf(s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf(s, "%08lx", x)
+#endif /* not BFD64 */
+#define printf_vma(x) fprintf_vma(stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+
+/** File formats */
+
+typedef enum bfd_format {
+ bfd_unknown = 0, /* file format is unknown */
+ bfd_object, /* linker/assember/compiler output */
+ bfd_archive, /* object archive file */
+ bfd_core, /* core dump */
+ bfd_type_end} /* marks the end; don't use it! */
+ bfd_format;
+
+/* Object file flag values */
+#define NO_FLAGS 0x00
+#define HAS_RELOC 0x01
+#define EXEC_P 0x02
+#define HAS_LINENO 0x04
+#define HAS_DEBUG 0x08
+#define HAS_SYMS 0x10
+#define HAS_LOCALS 0x20
+#define DYNAMIC 0x40
+#define WP_TEXT 0x80
+#define D_PAGED 0x100
+#define BFD_IS_RELAXABLE 0x200
+
+/* symbols and relocation */
+
+typedef unsigned long symindex;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+typedef enum bfd_symclass {
+ bfd_symclass_unknown = 0,
+ bfd_symclass_fcommon, /* fortran common symbols */
+ bfd_symclass_global, /* global symbol, what a surprise */
+ bfd_symclass_debugger, /* some debugger symbol */
+ bfd_symclass_undefined /* none known */
+ } symclass;
+
+
+/* general purpose part of a symbol;
+ target specific parts will be found in libcoff.h, liba.out.h etc */
+
+
+#define bfd_get_section(x) ((x)->section)
+#define bfd_get_output_section(x) ((x)->section->output_section)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#define bfd_asymbol_bfd(x) ((x)->the_bfd)
+#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour)
+
+/* This is a type pun with struct ranlib on purpose! */
+typedef struct carsym {
+ char *name;
+ file_ptr file_offset; /* look here to find the file */
+} carsym; /* to make these you call a carsymogen */
+
+
+/* Used in generating armaps. Perhaps just a forward definition would do? */
+struct orl { /* output ranlib */
+ char **name; /* symbol name */
+ file_ptr pos; /* bfd* or file position */
+ int namidx; /* index into string table */
+};
+
+
+
+/* Linenumber stuff */
+typedef struct lineno_cache_entry {
+ unsigned int line_number; /* Linenumber from start of function*/
+ union {
+ struct symbol_cache_entry *sym; /* Function name */
+ unsigned long offset; /* Offset into section */
+ } u;
+} alent;
+
+/* object and core file sections */
+
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+/** Error handling */
+
+typedef enum bfd_error {
+ no_error = 0, system_call_error, invalid_target,
+ wrong_format, invalid_operation, no_memory,
+ no_symbols, no_relocation_info,
+ no_more_archived_files, malformed_archive,
+ symbol_not_found, file_not_recognized,
+ file_ambiguously_recognized, no_contents,
+ bfd_error_nonrepresentable_section,
+ no_debug_section, bad_value,
+
+ /* An input file is shorter than expected. */
+ file_truncated,
+
+ invalid_error_code} bfd_ec;
+
+extern bfd_ec bfd_error;
+struct reloc_cache_entry;
+struct bfd_seclet;
+
+
+typedef struct bfd_error_vector {
+ void (* nonrepresentable_section ) PARAMS ((CONST bfd *CONST abfd,
+ CONST char *CONST name));
+ void (* undefined_symbol) PARAMS ((CONST struct reloc_cache_entry *rel,
+ CONST struct bfd_seclet *sec));
+ void (* reloc_value_truncated) PARAMS ((CONST struct
+ reloc_cache_entry *rel,
+ struct bfd_seclet *sec));
+
+ void (* reloc_dangerous) PARAMS ((CONST struct reloc_cache_entry *rel,
+ CONST struct bfd_seclet *sec));
+
+} bfd_error_vector_type;
+
+CONST char *bfd_errmsg PARAMS ((bfd_ec error_tag));
+void bfd_perror PARAMS ((CONST char *message));
+
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type; /* */
+ CONST char *name; /* Symbol name. */
+ char stab_other; /* Unused. */
+ short stab_desc; /* Info for N_TYPE. */
+ CONST char *stab_name;
+} symbol_info;
+
+/* The code that implements targets can initialize a jump table with this
+ macro. It must name all its routines the same way (a prefix plus
+ the standard routine suffix), or it must #define the routines that
+ are not so named, before calling JUMP_TABLE in the initializer. */
+
+/* Semi-portable string concatenation in cpp.
+ The CAT4 hack is to avoid a problem with some strict ANSI C preprocessors.
+ The problem is, "32_" is not a valid preprocessing token, and we don't
+ want extra underscores (e.g., "nlm_32_"). The XCAT2 macro will cause the
+ inner CAT macros to be evaluated first, producing still-valid pp-tokens.
+ Then the final concatenation can be done. (Sigh.) */
+#ifndef CAT
+#ifdef SABER
+#define CAT(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#define CAT4(a,b,c,d) a##b##c##d
+#else
+#ifdef __STDC__
+#define CAT(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#define XCAT2(a,b) CAT(a,b)
+#define CAT4(a,b,c,d) XCAT2(CAT(a,b),CAT(c,d))
+#else
+#define CAT(a,b) a/**/b
+#define CAT3(a,b,c) a/**/b/**/c
+#define CAT4(a,b,c,d) a/**/b/**/c/**/d
+#endif
+#endif
+#endif
+
+#define JUMP_TABLE(NAME)\
+CAT(NAME,_core_file_failing_command),\
+CAT(NAME,_core_file_failing_signal),\
+CAT(NAME,_core_file_matches_executable_p),\
+CAT(NAME,_slurp_armap),\
+CAT(NAME,_slurp_extended_name_table),\
+CAT(NAME,_truncate_arname),\
+CAT(NAME,_write_armap),\
+CAT(NAME,_close_and_cleanup),\
+CAT(NAME,_set_section_contents),\
+CAT(NAME,_get_section_contents),\
+CAT(NAME,_new_section_hook),\
+CAT(NAME,_get_symtab_upper_bound),\
+CAT(NAME,_get_symtab),\
+CAT(NAME,_get_reloc_upper_bound),\
+CAT(NAME,_canonicalize_reloc),\
+CAT(NAME,_make_empty_symbol),\
+CAT(NAME,_print_symbol),\
+CAT(NAME,_get_symbol_info),\
+CAT(NAME,_get_lineno),\
+CAT(NAME,_set_arch_mach),\
+CAT(NAME,_openr_next_archived_file),\
+CAT(NAME,_find_nearest_line),\
+CAT(NAME,_generic_stat_arch_elt),\
+CAT(NAME,_sizeof_headers),\
+CAT(NAME,_bfd_debug_info_start),\
+CAT(NAME,_bfd_debug_info_end),\
+CAT(NAME,_bfd_debug_info_accumulate),\
+CAT(NAME,_bfd_get_relocated_section_contents),\
+CAT(NAME,_bfd_relax_section),\
+CAT(NAME,_bfd_seclet_link),\
+CAT(NAME,_bfd_reloc_type_lookup),\
+CAT(NAME,_bfd_make_debug_symbol)
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+
+/* User program access to BFD facilities */
+
+/* Cast from const char * to char * so that caller can assign to
+ a char * without a warning. */
+#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
+#define bfd_get_format(abfd) ((abfd)->format)
+#define bfd_get_target(abfd) ((abfd)->xvec->name)
+#define bfd_get_file_flags(abfd) ((abfd)->flags)
+#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags)
+#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+/* Byte swapping routines. */
+
+bfd_vma bfd_getb64 PARAMS ((unsigned char *));
+bfd_vma bfd_getl64 PARAMS ((unsigned char *));
+bfd_signed_vma bfd_getb_signed_64 PARAMS ((unsigned char *));
+bfd_signed_vma bfd_getl_signed_64 PARAMS ((unsigned char *));
+bfd_vma bfd_getb32 PARAMS ((unsigned char *));
+bfd_vma bfd_getl32 PARAMS ((unsigned char *));
+bfd_signed_vma bfd_getb_signed_32 PARAMS ((unsigned char *));
+bfd_signed_vma bfd_getl_signed_32 PARAMS ((unsigned char *));
+bfd_vma bfd_getb16 PARAMS ((unsigned char *));
+bfd_vma bfd_getl16 PARAMS ((unsigned char *));
+bfd_signed_vma bfd_getb_signed_16 PARAMS ((unsigned char *));
+bfd_signed_vma bfd_getl_signed_16 PARAMS ((unsigned char *));
+void bfd_putb64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl64 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl32 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putb16 PARAMS ((bfd_vma, unsigned char *));
+void bfd_putl16 PARAMS ((bfd_vma, unsigned char *));
+
+/* And more from the source. */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((CONST char *filename, CONST char*target));
+
+bfd *
+bfd_fdopenr PARAMS ((CONST char *filename, CONST char *target, int fd));
+
+bfd *
+bfd_openw PARAMS ((CONST char *filename, CONST char *target));
+
+boolean
+bfd_close PARAMS ((bfd *));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd_size_type
+bfd_alloc_size PARAMS ((bfd *abfd));
+
+bfd *
+bfd_create PARAMS ((CONST char *filename, bfd *templ));
+
+
+ /* Byte swapping macros for user section data. */
+
+#define bfd_put_8(abfd, val, ptr) \
+ (*((unsigned char *)(ptr)) = (unsigned char)val)
+#define bfd_put_signed_8 \
+ bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+ (*(unsigned char *)(ptr))
+#define bfd_get_signed_8(abfd, ptr) \
+ ((*(unsigned char *)(ptr) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+ bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+ bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+ bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+
+ /* Byte swapping macros for file header data. */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+ bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+ bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_h_putx16,(val,ptr))
+#define bfd_h_put_signed_16 \
+ bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx16,(ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_h_putx32,(val,ptr))
+#define bfd_h_put_signed_32 \
+ bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx32,(ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_h_putx64,(val, ptr))
+#define bfd_h_put_signed_64 \
+ bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx64,(ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr))
+
+typedef struct sec
+{
+ /* The name of the section, the name isn't a copy, the pointer is
+ the same as that passed to bfd_make_section. */
+
+ CONST char *name;
+
+ /* Which section is it 0.nth */
+
+ int index;
+
+ /* The next section in the list belonging to the BFD, or NULL. */
+
+ struct sec *next;
+
+ /* The field flags contains attributes of the section. Some of
+ flags are read in from the object file, and some are
+ synthesized from other information. */
+
+ flagword flags;
+
+#define SEC_NO_FLAGS 0x000
+
+ /* Tells the OS to allocate space for this section when loaded.
+ This would clear for a section containing debug information
+ only. */
+#define SEC_ALLOC 0x001
+
+ /* Tells the OS to load the section from the file when loading.
+ This would be clear for a .bss section */
+#define SEC_LOAD 0x002
+
+ /* The section contains data still to be relocated, so there will
+ be some relocation information too. */
+#define SEC_RELOC 0x004
+
+#if 0 /* Obsolete ? */
+#define SEC_BALIGN 0x008
+#endif
+
+ /* A signal to the OS that the section contains read only
+ data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. When a back end sees a symbol
+ which should be used in a constructor list, it creates a new
+ section for the type of name (eg <<__CTOR_LIST__>>), attaches
+ the symbol to it and builds a relocation. To build the lists
+ of constructors, all the linker has to do is catenate all the
+ sections called <<__CTOR_LIST__>> and relocte the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section is a constuctor, and should be placed at the
+ end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS 0x3100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>, a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* An instruction to the linker not to output sections
+ containing this flag even if they have information which
+ would normally be written. */
+#define SEC_NEVER_LOAD 0x400
+
+ /* The section is a shared library section. The linker must leave
+ these completely alone, as the vma and size are used when
+ the executable is loaded. */
+#define SEC_SHARED_LIBRARY 0x800
+
+ /* The section is a common section (symbols may be defined
+ multiple times, the value of a symbol is the amount of
+ space it requires, and the largest symbol value is the one
+ used). Most targets have exactly one of these (which we
+ translate to bfd_com_section), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ discarded. */
+#define SEC_DEBUGGING 0x10000
+
+ /* End of section flags. */
+
+ /* The virtual memory address of the section - where it will be
+ at run time. The symbols are relocated against this. The
+ user_set_vma flag is maintained by bfd; if it's not set, the
+ backend can assign addresses (for example, in <<a.out>>, where
+ the default address for <<.data>> is dependent on the specific
+ target and various flags). */
+
+ bfd_vma vma;
+ boolean user_set_vma;
+
+ /* The load address of the section - where it would be in a
+ rom image, really only used for writing section header
+ information. */
+
+ bfd_vma lma;
+
+ /* The size of the section in bytes, as it will be output.
+ contains a value even if the section has no contents (eg, the
+ size of <<.bss>>). This will be filled in after relocation */
+
+ bfd_size_type _cooked_size;
+
+ /* The size on disk of the section in bytes originally. Normally this
+ value is the same as the size, but if some relaxing has
+ been done, then this value will be bigger. */
+
+ bfd_size_type _raw_size;
+
+ /* If this section is going to be output, then this value is the
+ offset into the output section of the first byte in the input
+ section. Eg, if this was going to start at the 100th byte in
+ the output section, this value would be 100. */
+
+ bfd_vma output_offset;
+
+ /* The output section through which to map on output. */
+
+ struct sec *output_section;
+
+ /* The alignment requirement of the section, as an exponent - eg
+ 3 aligns to 2^3 (or 8) */
+
+ unsigned int alignment_power;
+
+ /* If an input section, a pointer to a vector of relocation
+ records for the data in this section. */
+
+ struct reloc_cache_entry *relocation;
+
+ /* If an output section, a pointer to a vector of pointers to
+ relocation records for the data in this section. */
+
+ struct reloc_cache_entry **orelocation;
+
+ /* The number of relocation records in one of the above */
+
+ unsigned reloc_count;
+
+ /* Information below is back end specific - and not always used
+ or updated. */
+
+ /* File position of section data */
+
+ file_ptr filepos;
+
+ /* File position of relocation info */
+
+ file_ptr rel_filepos;
+
+ /* File position of line data */
+
+ file_ptr line_filepos;
+
+ /* Pointer to data for applications */
+
+ PTR userdata;
+
+ struct lang_output_section *otheruserdata;
+
+ /* Attached line number information */
+
+ alent *lineno;
+
+ /* Number of line number records */
+
+ unsigned int lineno_count;
+
+ /* When a section is being output, this value changes as more
+ linenumbers are written out */
+
+ file_ptr moving_line_filepos;
+
+ /* what the section number is in the target world */
+
+ int target_index;
+
+ PTR used_by_bfd;
+
+ /* If this is a constructor section then here is a list of the
+ relocations created to relocate items within it. */
+
+ struct relent_chain *constructor_chain;
+
+ /* The BFD which owns the section. */
+
+ bfd *owner;
+
+ boolean reloc_done;
+ /* A symbol which points at this section only */
+ struct symbol_cache_entry *symbol;
+ struct symbol_cache_entry **symbol_ptr_ptr;
+
+ struct bfd_seclet *seclets_head;
+ struct bfd_seclet *seclets_tail;
+} asection ;
+
+
+ /* These sections are global, and are managed by BFD. The application
+ and target back end are not permitted to change the values in
+ these sections. */
+#define BFD_ABS_SECTION_NAME "*ABS*"
+#define BFD_UND_SECTION_NAME "*UND*"
+#define BFD_COM_SECTION_NAME "*COM*"
+#define BFD_IND_SECTION_NAME "*IND*"
+
+ /* the absolute section */
+extern asection bfd_abs_section;
+ /* Pointer to the undefined section */
+extern asection bfd_und_section;
+ /* Pointer to the common section */
+extern asection bfd_com_section;
+ /* Pointer to the indirect section */
+extern asection bfd_ind_section;
+
+extern struct symbol_cache_entry *bfd_abs_symbol;
+extern struct symbol_cache_entry *bfd_com_symbol;
+extern struct symbol_cache_entry *bfd_und_symbol;
+extern struct symbol_cache_entry *bfd_ind_symbol;
+#define bfd_get_section_size_before_reloc(section) \
+ (section->reloc_done ? (abort(),1): (section)->_raw_size)
+#define bfd_get_section_size_after_reloc(section) \
+ ((section->reloc_done) ? (section)->_cooked_size: (abort(),1))
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, CONST char *name));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *, CONST char *name));
+
+asection *
+bfd_make_section_anyway PARAMS ((bfd *, CONST char *name));
+
+asection *
+bfd_make_section PARAMS ((bfd *, CONST char *name));
+
+boolean
+bfd_set_section_flags PARAMS ((bfd *, asection *, flagword));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+ void (*func)(bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *, asection *, bfd_size_type val));
+
+boolean
+bfd_set_section_contents
+ PARAMS ((bfd *abfd,
+ asection *section,
+ PTR data,
+ file_ptr offset,
+ bfd_size_type count));
+
+boolean
+bfd_get_section_contents
+ PARAMS ((bfd *abfd, asection *section, PTR location,
+ file_ptr offset, bfd_size_type count));
+
+enum bfd_architecture
+{
+ bfd_arch_unknown, /* File arch not known */
+ bfd_arch_obscure, /* Arch known, not one of these */
+ bfd_arch_m68k, /* Motorola 68xxx */
+ bfd_arch_vax, /* DEC Vax */
+ bfd_arch_i960, /* Intel 960 */
+ /* The order of the following is important.
+ lower number indicates a machine type that
+ only accepts a subset of the instructions
+ available to machines with higher numbers.
+ The exception is the "ca", which is
+ incompatible with all other machines except
+ "core". */
+
+#define bfd_mach_i960_core 1
+#define bfd_mach_i960_ka_sa 2
+#define bfd_mach_i960_kb_sb 3
+#define bfd_mach_i960_mc 4
+#define bfd_mach_i960_xa 5
+#define bfd_mach_i960_ca 6
+
+ bfd_arch_a29k, /* AMD 29000 */
+ bfd_arch_sparc, /* SPARC */
+ bfd_arch_mips, /* MIPS Rxxxx */
+ bfd_arch_i386, /* Intel 386 */
+ bfd_arch_we32k, /* AT&T WE32xxx */
+ bfd_arch_tahoe, /* CCI/Harris Tahoe */
+ bfd_arch_i860, /* Intel 860 */
+ bfd_arch_romp, /* IBM ROMP PC/RT */
+ bfd_arch_alliant, /* Alliant */
+ bfd_arch_convex, /* Convex */
+ bfd_arch_m88k, /* Motorola 88xxx */
+ bfd_arch_pyramid, /* Pyramid Technology */
+ bfd_arch_h8300, /* Hitachi H8/300 */
+#define bfd_mach_h8300 1
+#define bfd_mach_h8300h 2
+ bfd_arch_rs6000, /* IBM RS/6000 */
+ bfd_arch_hppa, /* HP PA RISC */
+ bfd_arch_z8k, /* Zilog Z8000 */
+#define bfd_mach_z8001 1
+#define bfd_mach_z8002 2
+ bfd_arch_h8500, /* Hitachi H8/500 */
+ bfd_arch_sh, /* Hitachi SH */
+ bfd_arch_alpha, /* Dec Alpha */
+ bfd_arch_last
+ };
+
+typedef struct bfd_arch_info
+{
+ int bits_per_word;
+ int bits_per_address;
+ int bits_per_byte;
+ enum bfd_architecture arch;
+ long mach;
+ char *arch_name;
+ CONST char *printable_name;
+ unsigned int section_align_power;
+ /* true if this is the default machine for the architecture */
+ boolean the_default;
+ CONST struct bfd_arch_info * (*compatible)
+ PARAMS ((CONST struct bfd_arch_info *a,
+ CONST struct bfd_arch_info *b));
+
+ boolean (*scan) PARAMS ((CONST struct bfd_arch_info *, CONST char *));
+ /* How to disassemble an instruction, producing a printable
+ representation on a specified stdio stream. This isn't
+ defined for most processors at present, because of the size
+ of the additional tables it would drag in, and because gdb
+ wants to use a different interface. */
+ unsigned int (*disassemble) PARAMS ((bfd_vma addr, CONST char *data,
+ PTR stream));
+
+ struct bfd_arch_info *next;
+} bfd_arch_info_type;
+CONST char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+bfd_arch_info_type *
+bfd_scan_arch PARAMS ((CONST char *));
+
+CONST bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+ CONST bfd *abfd,
+ CONST bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *, bfd_arch_info_type *));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *));
+
+bfd_arch_info_type *
+bfd_lookup_arch
+ PARAMS ((enum bfd_architecture
+ arch,
+ long machine));
+
+CONST char *
+bfd_printable_arch_mach
+ PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+ /* No errors detected */
+ bfd_reloc_ok,
+
+ /* The relocation was performed, but there was an overflow. */
+ bfd_reloc_overflow,
+
+ /* The address to relocate was not within the section supplied. */
+ bfd_reloc_outofrange,
+
+ /* Used by special functions */
+ bfd_reloc_continue,
+
+ /* Unused */
+ bfd_reloc_notsupported,
+
+ /* Unsupported relocation size requested. */
+ bfd_reloc_other,
+
+ /* The symbol to relocate against was undefined. */
+ bfd_reloc_undefined,
+
+ /* The relocation was performed, but may not be ok - presently
+ generated only when linking i960 coff files with i960 b.out
+ symbols. */
+ bfd_reloc_dangerous
+ }
+ bfd_reloc_status_type;
+
+
+typedef struct reloc_cache_entry
+{
+ /* A pointer into the canonical table of pointers */
+ struct symbol_cache_entry **sym_ptr_ptr;
+
+ /* offset in section */
+ bfd_size_type address;
+
+ /* addend for relocation value */
+ bfd_vma addend;
+
+ /* Pointer to how to perform the required relocation */
+ CONST struct reloc_howto_struct *howto;
+
+} arelent;
+enum complain_overflow
+{
+ /* Do not complain on overflow. */
+ complain_overflow_dont,
+
+ /* Complain if the bitfield overflows, whether it is considered
+ as signed or unsigned. */
+ complain_overflow_bitfield,
+
+ /* Complain if the value overflows when considered as signed
+ number. */
+ complain_overflow_signed,
+
+ /* Complain if the value overflows when considered as an
+ unsigned number. */
+ complain_overflow_unsigned
+};
+
+typedef CONST struct reloc_howto_struct
+{
+ /* The type field has mainly a documetary use - the back end can
+ to what it wants with it, though the normally the back end's
+ external idea of what a reloc number would be would be stored
+ in this field. For example, the a PC relative word relocation
+ in a coff environment would have the type 023 - because that's
+ what the outside world calls a R_PCRWORD reloc. */
+ unsigned int type;
+
+ /* The value the final relocation is shifted right by. This drops
+ unwanted data from the relocation. */
+ unsigned int rightshift;
+
+ /* The size of the item to be relocated. This is *not* a
+ power-of-two measure.
+ 0 : one byte
+ 1 : two bytes
+ 2 : four bytes
+ 3 : nothing done (unless special_function is nonzero)
+ 4 : eight bytes
+ -2 : two bytes, result should be subtracted from the
+ data instead of added
+ There is currently no trivial way to extract a "number of
+ bytes" from a howto pointer. */
+ int size;
+
+ /* The number of bits in the item to be relocated. This is used
+ when doing overflow checking. */
+ unsigned int bitsize;
+
+ /* Notes that the relocation is relative to the location in the
+ data section of the addend. The relocation function will
+ subtract from the relocation value the address of the location
+ being relocated. */
+ boolean pc_relative;
+
+ /* The bit position of the reloc value in the destination.
+ The relocated value is left shifted by this amount. */
+ unsigned int bitpos;
+
+ /* What type of overflow error should be checked for when
+ relocating. */
+ enum complain_overflow complain_on_overflow;
+
+ /* If this field is non null, then the supplied function is
+ called rather than the normal function. This allows really
+ strange relocation methods to be accomodated (e.g., i960 callj
+ instructions). */
+ bfd_reloc_status_type (*special_function)
+ PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ struct symbol_cache_entry *symbol,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd));
+
+ /* The textual name of the relocation type. */
+ char *name;
+
+ /* When performing a partial link, some formats must modify the
+ relocations rather than the data - this flag signals this.*/
+ boolean partial_inplace;
+
+ /* The src_mask is used to select what parts of the read in data
+ are to be used in the relocation sum. E.g., if this was an 8 bit
+ bit of data which we read and relocated, this would be
+ 0x000000ff. When we have relocs which have an addend, such as
+ sun4 extended relocs, the value in the offset part of a
+ relocating field is garbage so we never use it. In this case
+ the mask would be 0x00000000. */
+ bfd_vma src_mask;
+
+ /* The dst_mask is what parts of the instruction are replaced
+ into the instruction. In most cases src_mask == dst_mask,
+ except in the above special case, where dst_mask would be
+ 0x000000ff, and src_mask would be 0x00000000. */
+ bfd_vma dst_mask;
+
+ /* When some formats create PC relative instructions, they leave
+ the value of the pc of the place being relocated in the offset
+ slot of the instruction, so that a PC relative relocation can
+ be made just by adding in an ordinary offset (e.g., sun3 a.out).
+ Some formats leave the displacement part of an instruction
+ empty (e.g., m88k bcs), this flag signals the fact.*/
+ boolean pcrel_offset;
+
+} reloc_howto_type;
+#define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+ {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC}
+#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN)
+
+#define HOWTO_PREPARE(relocation, symbol) \
+ { \
+ if (symbol != (asymbol *)NULL) { \
+ if (bfd_is_com_section (symbol->section)) { \
+ relocation = 0; \
+ } \
+ else { \
+ relocation = symbol->value; \
+ } \
+ } \
+}
+typedef unsigned char bfd_byte;
+
+typedef struct relent_chain {
+ arelent relent;
+ struct relent_chain *next;
+} arelent_chain;
+bfd_reloc_status_type
+
+bfd_perform_relocation
+ PARAMS ((bfd * abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd));
+
+typedef enum bfd_reloc_code_real
+{
+ /* Basic absolute relocations */
+ BFD_RELOC_64,
+ BFD_RELOC_32,
+ BFD_RELOC_16,
+ BFD_RELOC_8,
+
+ /* PC-relative relocations */
+ BFD_RELOC_64_PCREL,
+ BFD_RELOC_32_PCREL,
+ BFD_RELOC_24_PCREL, /* used by i960 */
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_8_PCREL,
+
+ /* Linkage-table relative */
+ BFD_RELOC_32_BASEREL,
+ BFD_RELOC_16_BASEREL,
+ BFD_RELOC_8_BASEREL,
+
+ /* The type of reloc used to build a contructor table - at the moment
+ probably a 32 bit wide abs address, but the cpu can choose. */
+ BFD_RELOC_CTOR,
+
+ /* 8 bits wide, but used to form an address like 0xffnn */
+ BFD_RELOC_8_FFnn,
+
+ /* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit
+ word displacement, e.g. for SPARC) */
+ BFD_RELOC_32_PCREL_S2,
+
+ /* High 22 bits of 32-bit value, placed into lower 22 bits of
+ target word; simple reloc. */
+ BFD_RELOC_HI22,
+ /* Low 10 bits. */
+ BFD_RELOC_LO10,
+
+ /* Reloc types used for i960/b.out. */
+ BFD_RELOC_I960_CALLJ,
+
+ /* now for the sparc/elf codes */
+ BFD_RELOC_NONE, /* actually used */
+ BFD_RELOC_SPARC_WDISP22,
+ BFD_RELOC_SPARC22,
+ BFD_RELOC_SPARC13,
+ BFD_RELOC_SPARC_GOT10,
+ BFD_RELOC_SPARC_GOT13,
+ BFD_RELOC_SPARC_GOT22,
+ BFD_RELOC_SPARC_PC10,
+ BFD_RELOC_SPARC_PC22,
+ BFD_RELOC_SPARC_WPLT30,
+ BFD_RELOC_SPARC_COPY,
+ BFD_RELOC_SPARC_GLOB_DAT,
+ BFD_RELOC_SPARC_JMP_SLOT,
+ BFD_RELOC_SPARC_RELATIVE,
+ BFD_RELOC_SPARC_UA32,
+
+ /* these are a.out specific? */
+ BFD_RELOC_SPARC_BASE13,
+ BFD_RELOC_SPARC_BASE22,
+
+
+ /* Bits 27..2 of the relocation address shifted right 2 bits;
+ simple reloc otherwise. */
+ BFD_RELOC_MIPS_JMP,
+
+ /* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) */
+ BFD_RELOC_16_PCREL_S2,
+
+ /* High 16 bits of 32-bit value; simple reloc. */
+ BFD_RELOC_HI16,
+ /* High 16 bits of 32-bit value but the low 16 bits will be sign
+ extended and added to form the final result. If the low 16
+ bits form a negative number, we need to add one to the high value
+ to compensate for the borrow when the low bits are added. */
+ BFD_RELOC_HI16_S,
+ /* Low 16 bits. */
+ BFD_RELOC_LO16,
+
+ /* 16 bit relocation relative to the global pointer. */
+ BFD_RELOC_MIPS_GPREL,
+
+ /* These are, so far, specific to HPPA processors. I'm not sure that some
+ don't duplicate other reloc types, such as BFD_RELOC_32 and _32_PCREL.
+ Also, many more were in the list I got that don't fit in well in the
+ model BFD uses, so I've omitted them for now. If we do make this reloc
+ type get used for code that really does implement the funky reloc types,
+ they'll have to be added to this list. */
+ BFD_RELOC_HPPA_32,
+ BFD_RELOC_HPPA_11,
+ BFD_RELOC_HPPA_14,
+ BFD_RELOC_HPPA_17,
+
+ BFD_RELOC_HPPA_L21,
+ BFD_RELOC_HPPA_R11,
+ BFD_RELOC_HPPA_R14,
+ BFD_RELOC_HPPA_R17,
+ BFD_RELOC_HPPA_LS21,
+ BFD_RELOC_HPPA_RS11,
+ BFD_RELOC_HPPA_RS14,
+ BFD_RELOC_HPPA_RS17,
+ BFD_RELOC_HPPA_LD21,
+ BFD_RELOC_HPPA_RD11,
+ BFD_RELOC_HPPA_RD14,
+ BFD_RELOC_HPPA_RD17,
+ BFD_RELOC_HPPA_LR21,
+ BFD_RELOC_HPPA_RR14,
+ BFD_RELOC_HPPA_RR17,
+
+ BFD_RELOC_HPPA_GOTOFF_11,
+ BFD_RELOC_HPPA_GOTOFF_14,
+ BFD_RELOC_HPPA_GOTOFF_L21,
+ BFD_RELOC_HPPA_GOTOFF_R11,
+ BFD_RELOC_HPPA_GOTOFF_R14,
+ BFD_RELOC_HPPA_GOTOFF_LS21,
+ BFD_RELOC_HPPA_GOTOFF_RS11,
+ BFD_RELOC_HPPA_GOTOFF_RS14,
+ BFD_RELOC_HPPA_GOTOFF_LD21,
+ BFD_RELOC_HPPA_GOTOFF_RD11,
+ BFD_RELOC_HPPA_GOTOFF_RD14,
+ BFD_RELOC_HPPA_GOTOFF_LR21,
+ BFD_RELOC_HPPA_GOTOFF_RR14,
+
+ BFD_RELOC_HPPA_DLT_32,
+ BFD_RELOC_HPPA_DLT_11,
+ BFD_RELOC_HPPA_DLT_14,
+ BFD_RELOC_HPPA_DLT_L21,
+ BFD_RELOC_HPPA_DLT_R11,
+ BFD_RELOC_HPPA_DLT_R14,
+
+ BFD_RELOC_HPPA_ABS_CALL_11,
+ BFD_RELOC_HPPA_ABS_CALL_14,
+ BFD_RELOC_HPPA_ABS_CALL_17,
+ BFD_RELOC_HPPA_ABS_CALL_L21,
+ BFD_RELOC_HPPA_ABS_CALL_R11,
+ BFD_RELOC_HPPA_ABS_CALL_R14,
+ BFD_RELOC_HPPA_ABS_CALL_R17,
+ BFD_RELOC_HPPA_ABS_CALL_LS21,
+ BFD_RELOC_HPPA_ABS_CALL_RS11,
+ BFD_RELOC_HPPA_ABS_CALL_RS14,
+ BFD_RELOC_HPPA_ABS_CALL_RS17,
+ BFD_RELOC_HPPA_ABS_CALL_LD21,
+ BFD_RELOC_HPPA_ABS_CALL_RD11,
+ BFD_RELOC_HPPA_ABS_CALL_RD14,
+ BFD_RELOC_HPPA_ABS_CALL_RD17,
+ BFD_RELOC_HPPA_ABS_CALL_LR21,
+ BFD_RELOC_HPPA_ABS_CALL_RR14,
+ BFD_RELOC_HPPA_ABS_CALL_RR17,
+
+ BFD_RELOC_HPPA_PCREL_CALL_11,
+ BFD_RELOC_HPPA_PCREL_CALL_12,
+ BFD_RELOC_HPPA_PCREL_CALL_14,
+ BFD_RELOC_HPPA_PCREL_CALL_17,
+ BFD_RELOC_HPPA_PCREL_CALL_L21,
+ BFD_RELOC_HPPA_PCREL_CALL_R11,
+ BFD_RELOC_HPPA_PCREL_CALL_R14,
+ BFD_RELOC_HPPA_PCREL_CALL_R17,
+ BFD_RELOC_HPPA_PCREL_CALL_LS21,
+ BFD_RELOC_HPPA_PCREL_CALL_RS11,
+ BFD_RELOC_HPPA_PCREL_CALL_RS14,
+ BFD_RELOC_HPPA_PCREL_CALL_RS17,
+ BFD_RELOC_HPPA_PCREL_CALL_LD21,
+ BFD_RELOC_HPPA_PCREL_CALL_RD11,
+ BFD_RELOC_HPPA_PCREL_CALL_RD14,
+ BFD_RELOC_HPPA_PCREL_CALL_RD17,
+ BFD_RELOC_HPPA_PCREL_CALL_LR21,
+ BFD_RELOC_HPPA_PCREL_CALL_RR14,
+ BFD_RELOC_HPPA_PCREL_CALL_RR17,
+
+ BFD_RELOC_HPPA_PLABEL_32,
+ BFD_RELOC_HPPA_PLABEL_11,
+ BFD_RELOC_HPPA_PLABEL_14,
+ BFD_RELOC_HPPA_PLABEL_L21,
+ BFD_RELOC_HPPA_PLABEL_R11,
+ BFD_RELOC_HPPA_PLABEL_R14,
+
+ BFD_RELOC_HPPA_UNWIND_ENTRY,
+ BFD_RELOC_HPPA_UNWIND_ENTRIES,
+
+ /* i386/elf relocations */
+ BFD_RELOC_386_GOT32,
+ BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_COPY,
+ BFD_RELOC_386_GLOB_DAT,
+ BFD_RELOC_386_JUMP_SLOT,
+ BFD_RELOC_386_RELATIVE,
+ BFD_RELOC_386_GOTOFF,
+ BFD_RELOC_386_GOTPC,
+
+ /* this must be the highest numeric value */
+ BFD_RELOC_UNUSED
+ } bfd_reloc_code_real_type;
+CONST struct reloc_howto_struct *
+
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+
+typedef struct symbol_cache_entry
+{
+ /* A pointer to the BFD which owns the symbol. This information
+ is necessary so that a back end can work out what additional
+ information (invisible to the application writer) is carried
+ with the symbol.
+
+ This field is *almost* redundant, since you can use section->owner
+ instead, except that some symbols point to the global sections
+ bfd_{abs,com,und}_section. This could be fixed by making
+ these globals be per-bfd (or per-target-flavor). FIXME. */
+
+ struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */
+
+ /* The text of the symbol. The name is left alone, and not copied - the
+ application may not alter it. */
+ CONST char *name;
+
+ /* The value of the symbol. This really should be a union of a
+ numeric value with a pointer, since some flags indicate that
+ a pointer to another symbol is stored here. */
+ symvalue value;
+
+ /* Attributes of a symbol: */
+
+#define BSF_NO_FLAGS 0x00
+
+ /* The symbol has local scope; <<static>> in <<C>>. The value
+ is the offset into the section of the data. */
+#define BSF_LOCAL 0x01
+
+ /* The symbol has global scope; initialized data in <<C>>. The
+ value is the offset into the section of the data. */
+#define BSF_GLOBAL 0x02
+
+ /* The symbol has global scope, and is exported. The value is
+ the offset into the section of the data. */
+#define BSF_EXPORT BSF_GLOBAL /* no real difference */
+
+ /* A normal C symbol would be one of:
+ <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+ <<BSF_GLOBAL>> */
+
+ /* The symbol is a debugging record. The value has an arbitary
+ meaning. */
+#define BSF_DEBUGGING 0x08
+
+ /* The symbol denotes a function entry point. Used in ELF,
+ perhaps others someday. */
+#define BSF_FUNCTION 0x10
+
+ /* Used by the linker. */
+#define BSF_KEEP 0x20
+#define BSF_KEEP_G 0x40
+
+ /* A weak global symbol, overridable without warnings by
+ a regular global symbol of the same name. */
+#define BSF_WEAK 0x80
+
+ /* This symbol was created to point to a section, e.g. ELF's
+ STT_SECTION symbols. */
+#define BSF_SECTION_SYM 0x100
+
+ /* The symbol used to be a common symbol, but now it is
+ allocated. */
+#define BSF_OLD_COMMON 0x200
+
+ /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+ /* In some files the type of a symbol sometimes alters its
+ location in an output file - ie in coff a <<ISFCN>> symbol
+ which is also <<C_EXT>> symbol appears where it was
+ declared and not at the end of a section. This bit is set
+ by the target BFD part to convey this information. */
+
+#define BSF_NOT_AT_END 0x400
+
+ /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR 0x800
+
+ /* Signal that the symbol is a warning symbol. If the symbol
+ is a warning symbol, then the value field (I know this is
+ tacky) will point to the asymbol which when referenced will
+ cause the warning. */
+#define BSF_WARNING 0x1000
+
+ /* Signal that the symbol is indirect. The value of the symbol
+ is a pointer to an undefined asymbol which contains the
+ name to use instead. */
+#define BSF_INDIRECT 0x2000
+
+ /* BSF_FILE marks symbols that contain a file name. This is used
+ for ELF STT_FILE symbols. */
+#define BSF_FILE 0x4000
+
+ flagword flags;
+
+ /* A pointer to the section to which this symbol is
+ relative. This will always be non NULL, there are special
+ sections for undefined and absolute symbols */
+ struct sec *section;
+
+ /* Back end special data. This is being phased out in favour
+ of making this a union. */
+ PTR udata;
+
+} asymbol;
+#define get_symtab_upper_bound(abfd) \
+ BFD_SEND (abfd, _get_symtab_upper_bound, (abfd))
+#define bfd_canonicalize_symtab(abfd, location) \
+ BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+ (abfd, location))
+boolean
+bfd_set_symtab PARAMS ((bfd *, asymbol **, unsigned int ));
+
+void
+bfd_print_symbol_vandf PARAMS ((PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+struct _bfd
+{
+ /* The filename the application opened the BFD with. */
+ CONST char *filename;
+
+ /* A pointer to the target jump table. */
+ struct bfd_target *xvec;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char
+ *", and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. */
+ char *iostream;
+
+ /* Is the file being cached */
+
+ boolean cacheable;
+
+ /* Marks whether there was a default target specified when the
+ BFD was opened. This is used to select what matching algorithm
+ to use to chose the back end. */
+
+ boolean target_defaulted;
+
+ /* The caching routines use these to maintain a
+ least-recently-used list of BFDs */
+
+ struct _bfd *lru_prev, *lru_next;
+
+ /* When a file is closed by the caching routines, BFD retains
+ state information on the file here:
+ */
+
+ file_ptr where;
+
+ /* and here:*/
+
+ boolean opened_once;
+
+ /* Set if we have a locally maintained mtime value, rather than
+ getting it from the file each time: */
+
+ boolean mtime_set;
+
+ /* File modified time, if mtime_set is true: */
+
+ long mtime;
+
+ /* Reserved for an unimplemented file locking extension.*/
+
+ int ifd;
+
+ /* The format which belongs to the BFD.*/
+
+ bfd_format format;
+
+ /* The direction the BFD was opened with*/
+
+ enum bfd_direction {no_direction = 0,
+ read_direction = 1,
+ write_direction = 2,
+ both_direction = 3} direction;
+
+ /* Format_specific flags*/
+
+ flagword flags;
+
+ /* Currently my_archive is tested before adding origin to
+ anything. I believe that this can become always an add of
+ origin, with origin set to 0 for non archive files. */
+
+ file_ptr origin;
+
+ /* Remember when output has begun, to stop strange things
+ happening. */
+ boolean output_has_begun;
+
+ /* Pointer to linked list of sections*/
+ struct sec *sections;
+
+ /* The number of sections */
+ unsigned int section_count;
+
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+
+ /* Used for input and output*/
+ unsigned int symcount;
+
+ /* Symbol table for output BFD*/
+ struct symbol_cache_entry **outsymbols;
+
+ /* Pointer to structure which contains architecture information*/
+ struct bfd_arch_info *arch_info;
+
+ /* Stuff only useful for archives:*/
+ PTR arelt_data;
+ struct _bfd *my_archive;
+ struct _bfd *next;
+ struct _bfd *archive_head;
+ boolean has_armap;
+
+ /* Used by the back end to hold private data. */
+
+ union
+ {
+ struct aout_data_struct *aout_data;
+ struct artdata *aout_ar_data;
+ struct _oasys_data *oasys_obj_data;
+ struct _oasys_ar_data *oasys_ar_data;
+ struct coff_tdata *coff_obj_data;
+ struct ecoff_tdata *ecoff_obj_data;
+ struct ieee_data_struct *ieee_data;
+ struct ieee_ar_data_struct *ieee_ar_data;
+ struct srec_data_struct *srec_data;
+ struct tekhex_data_struct *tekhex_data;
+ struct elf_obj_tdata *elf_obj_data;
+ struct nlm_obj_tdata *nlm_obj_data;
+ struct bout_data_struct *bout_data;
+ struct sun_core_struct *sun_core_data;
+ struct trad_core_struct *trad_core_data;
+ struct hppa_data_struct *hppa_data;
+ struct hpux_core_struct *hpux_core_data;
+ struct sgi_core_struct *sgi_core_data;
+ struct lynx_core_struct *lynx_core_data;
+ struct osf_core_struct *osf_core_data;
+ PTR any;
+ } tdata;
+
+ /* Used by the application to hold private data*/
+ PTR usrdata;
+
+ /* Where all the allocated stuff under this BFD goes */
+ struct obstack memory;
+
+ /* Is this really needed in addition to usrdata? */
+ asymbol **ld_symbols;
+};
+
+unsigned int
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+unsigned int
+bfd_canonicalize_reloc
+ PARAMS ((bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms));
+
+boolean
+bfd_set_file_flags PARAMS ((bfd *abfd, flagword flags));
+
+void
+bfd_set_reloc
+ PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+
+ );
+
+boolean
+bfd_set_start_address PARAMS ((bfd *, bfd_vma));
+
+long
+bfd_get_mtime PARAMS ((bfd *));
+
+long
+bfd_get_size PARAMS ((bfd *));
+
+int
+bfd_get_gp_size PARAMS ((bfd *));
+
+void
+bfd_set_gp_size PARAMS ((bfd *, int));
+
+bfd_vma
+bfd_scan_vma PARAMS ((CONST char *string, CONST char **end, int base));
+
+#define bfd_sizeof_headers(abfd, reloc) \
+ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+ BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+
+ /* Do these three do anything useful at all, for any back end? */
+#define bfd_debug_info_start(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#define bfd_get_relocated_section_contents(abfd, seclet, data, relocateable) \
+ BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet, data, relocateable))
+
+#define bfd_relax_section(abfd, section, symbols) \
+ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols))
+
+#define bfd_seclet_link(abfd, data, relocateable) \
+ BFD_SEND (abfd, _bfd_seclet_link, (abfd, data, relocateable))
+symindex
+bfd_get_next_mapent PARAMS ((bfd *, symindex previous, carsym ** sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_get_elt_at_index PARAMS ((bfd * archive, int index));
+
+bfd*
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+CONST char *
+bfd_core_file_failing_command PARAMS ((bfd *));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *));
+
+boolean
+core_file_matches_executable_p
+ PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#define BFD_SEND(bfd, message, arglist) \
+ ((*((bfd)->xvec->message)) arglist)
+#define BFD_SEND_FMT(bfd, message, arglist) \
+ (((bfd)->xvec->message[(int)((bfd)->format)]) arglist)
+typedef struct bfd_target
+{
+ char *name;
+ enum target_flavour {
+ bfd_target_unknown_flavour,
+ bfd_target_aout_flavour,
+ bfd_target_coff_flavour,
+ bfd_target_ecoff_flavour,
+ bfd_target_elf_flavour,
+ bfd_target_ieee_flavour,
+ bfd_target_nlm_flavour,
+ bfd_target_oasys_flavour,
+ bfd_target_tekhex_flavour,
+ bfd_target_srec_flavour,
+ bfd_target_hppa_flavour} flavour;
+ boolean byteorder_big_p;
+ boolean header_byteorder_big_p;
+ flagword object_flags;
+ flagword section_flags;
+ char symbol_leading_char;
+ char ar_pad_char;
+ unsigned short ar_max_namelen;
+ unsigned int align_power_min;
+ bfd_vma (*bfd_getx64) PARAMS ((bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((bfd_byte *));
+ void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx32) PARAMS ((bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((bfd_byte *));
+ void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_getx16) PARAMS ((bfd_byte *));
+ bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((bfd_byte *));
+ void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx64) PARAMS ((bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((bfd_byte *));
+ void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx32) PARAMS ((bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((bfd_byte *));
+ void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+ bfd_vma (*bfd_h_getx16) PARAMS ((bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((bfd_byte *));
+ void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+ struct bfd_target * (*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+ boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+ boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+ char * (*_core_file_failing_command) PARAMS ((bfd *));
+ int (*_core_file_failing_signal) PARAMS ((bfd *));
+ boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+ boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+ boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+ void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *));
+ boolean (*write_armap) PARAMS ((bfd *arch,
+ unsigned int elength,
+ struct orl *map,
+ unsigned int orl_count,
+ int stridx));
+ boolean (*_close_and_cleanup) PARAMS ((bfd *));
+ boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+ boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+ boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+ unsigned int (*_get_symtab_upper_bound) PARAMS ((bfd *));
+ unsigned int (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+ struct symbol_cache_entry **));
+ unsigned int (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+ unsigned int (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+ struct symbol_cache_entry **));
+ struct symbol_cache_entry *
+ (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+ void (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+ struct symbol_cache_entry *,
+ bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+ void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+ struct symbol_cache_entry *,
+ symbol_info *));
+#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+ alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+
+ boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+
+ bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
+
+ boolean (*_bfd_find_nearest_line) PARAMS ((bfd *abfd,
+ struct sec *section, struct symbol_cache_entry **symbols,
+ bfd_vma offset, CONST char **file, CONST char **func,
+ unsigned int *line));
+
+ int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+
+ int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+
+ void (*_bfd_debug_info_start) PARAMS ((bfd *));
+ void (*_bfd_debug_info_end) PARAMS ((bfd *));
+ void (*_bfd_debug_info_accumulate) PARAMS ((bfd *, struct sec *));
+
+ bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
+ struct bfd_seclet *, bfd_byte *data,
+ boolean relocateable));
+
+ boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *,
+ struct symbol_cache_entry **));
+
+ boolean (*_bfd_seclet_link) PARAMS ((bfd *, PTR data,
+ boolean relocateable));
+ /* See documentation on reloc types. */
+ CONST struct reloc_howto_struct *
+ (*reloc_type_lookup) PARAMS ((bfd *abfd,
+ bfd_reloc_code_real_type code));
+
+ /* Back-door to allow format-aware applications to create debug symbols
+ while using BFD for everything else. Currently used by the assembler
+ when creating COFF files. */
+ asymbol * (*_bfd_make_debug_symbol) PARAMS ((
+ bfd *abfd,
+ void *ptr,
+ unsigned long size));
+ PTR backend_data;
+} bfd_target;
+bfd_target *
+bfd_find_target PARAMS ((CONST char *, bfd *));
+
+CONST char **
+bfd_target_list PARAMS ((void));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+bfd_set_format PARAMS ((bfd *, bfd_format));
+
+CONST char *
+bfd_format_string PARAMS ((bfd_format));
+
+#endif
diff --git a/gnu/usr.bin/gdb/bfd/cache.c b/gnu/usr.bin/gdb/bfd/cache.c
new file mode 100644
index 000000000000..f8cfd19fed5c
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/cache.c
@@ -0,0 +1,311 @@
+/* BFD library -- caching of file descriptors.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ File Caching
+
+ The file caching mechanism is embedded within BFD and allows
+ the application to open as many BFDs as it wants without
+ regard to the underlying operating system's file descriptor
+ limit (often as low as 20 open files). The module in
+ <<cache.c>> maintains a least recently used list of
+ <<BFD_CACHE_MAX_OPEN>> files, and exports the name
+ <<bfd_cache_lookup>> which runs around and makes sure that
+ the required BFD is open. If not, then it chooses a file to
+ close, closes it and opens the one wanted, returning its file
+ handle.
+
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/*
+INTERNAL_FUNCTION
+ BFD_CACHE_MAX_OPEN macro
+
+DESCRIPTION
+ The maximum number of files which the cache will keep open at
+ one time.
+
+.#define BFD_CACHE_MAX_OPEN 10
+
+*/
+
+
+static boolean
+bfd_cache_delete PARAMS ((bfd *));
+
+/* Number of bfds on the chain. All such bfds have their file open;
+ if it closed, they get snipd()d from the chain. */
+
+static int open_files;
+
+static bfd *cache_sentinel; /* Chain of BFDs with active fds we've
+ opened */
+
+/*
+INTERNAL_FUNCTION
+ bfd_last_cache
+
+SYNOPSIS
+ extern bfd *bfd_last_cache;
+
+DESCRIPTION
+ Zero, or a pointer to the topmost BFD on the chain. This is
+ used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
+ determine when it can avoid a function call.
+*/
+
+bfd *bfd_last_cache;
+
+/*
+ * INTERNAL_FUNCTION
+ * bfd_cache_lookup
+ *
+ * DESCRIPTION
+ * Checks to see if the required BFD is the same as the last one
+ * looked up. If so then it can use the iostream in the BFD with
+ * impunity, since it can't have changed since the last lookup,
+ * otherwise it has to perform the complicated lookup function
+ *
+ * .#define bfd_cache_lookup(x) \
+ * . ((x)==bfd_last_cache? \
+ * . (FILE*)(bfd_last_cache->iostream): \
+ * . bfd_cache_lookup_worker(x))
+ *
+ *
+ */
+
+static void
+DEFUN_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));
+ (void) bfd_cache_delete(kill);
+}
+
+/* Cuts the BFD abfd out of the chain in the cache */
+static void
+DEFUN(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 boolean
+DEFUN(bfd_cache_delete,(abfd),
+ bfd *abfd)
+{
+ boolean ret;
+
+ if (fclose ((FILE *)(abfd->iostream)) == 0)
+ ret = true;
+ else
+ {
+ ret = false;
+ bfd_error = system_call_error;
+ }
+ snip (abfd);
+ abfd->iostream = NULL;
+ open_files--;
+ bfd_last_cache = 0;
+ return ret;
+}
+
+static bfd *
+DEFUN(insert,(x,y),
+ bfd *x AND
+ 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;
+}
+
+
+/* Initialize a BFD by putting it on the cache LRU. */
+
+void
+DEFUN(bfd_cache_init,(abfd),
+ bfd *abfd)
+{
+ if (open_files >= BFD_CACHE_MAX_OPEN)
+ close_one ();
+ cache_sentinel = insert(abfd, cache_sentinel);
+ ++open_files;
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_cache_close
+
+DESCRIPTION
+ Remove the BFD from the cache. If the attached file is open,
+ then close it too.
+
+SYNOPSIS
+ boolean bfd_cache_close (bfd *);
+
+RETURNS
+ <<false>> is returned if closing the file fails, <<true>> is
+ returned if all is well.
+*/
+boolean
+DEFUN(bfd_cache_close,(abfd),
+ bfd *abfd)
+{
+ /* If this file is open then remove from the chain */
+ if (abfd->iostream)
+ {
+ return bfd_cache_delete(abfd);
+ }
+ else
+ {
+ return true;
+ }
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_open_file
+
+DESCRIPTION
+ 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. If the FILE
+ * returned is null, then there is won't have been put in the
+ cache, so it won't have to be removed from it.
+
+SYNOPSIS
+ FILE* bfd_open_file(bfd *);
+*/
+
+FILE *
+DEFUN(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, FOPEN_RB);
+ break;
+ case both_direction:
+ case write_direction:
+ if (abfd->opened_once == true) {
+ abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB);
+ if (!abfd->iostream) {
+ abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB);
+ }
+ } else {
+ /*open for creat */
+ abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
+ abfd->opened_once = true;
+ }
+ break;
+ }
+
+ if (abfd->iostream) {
+ bfd_cache_init (abfd);
+ }
+
+ return (FILE *)(abfd->iostream);
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_cache_lookup_worker
+
+DESCRIPTION
+ Called when the macro <<bfd_cache_lookup>> fails to find a
+ quick answer. Finds a file descriptor for this BFD. If
+ necessary, it open it. If there are already more than
+ BFD_CACHE_MAX_OPEN files open, it trys to close one first, to
+ avoid running out of file descriptors.
+
+SYNOPSIS
+ FILE *bfd_cache_lookup_worker(bfd *);
+
+*/
+
+FILE *
+DEFUN(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/gnu/usr.bin/gdb/bfd/coffgen.c b/gnu/usr.bin/gdb/bfd/coffgen.c
new file mode 100644
index 000000000000..94cc225d098c
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/coffgen.c
@@ -0,0 +1,1519 @@
+/* Support for the generic parts of COFF, for BFD.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Most of this hacked by Steve Chamberlain, sac@cygnus.com.
+ Split out of coffcode.h by Ian Taylor, ian@cygnus.com. */
+
+/* This file contains COFF code that is not dependent on any
+ particular COFF target. There is only one version of this file in
+ libbfd.a, so no target specific code may be put in here. Or, to
+ put it another way,
+
+ ********** DO NOT PUT TARGET SPECIFIC CODE IN THIS FILE **********
+
+ If you need to add some target specific behaviour, add a new hook
+ function to bfd_coff_backend_data.
+
+ Some of these functions are also called by the ECOFF routines.
+ Those functions may not use any COFF specific information, such as
+ coff_data (abfd). */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "coff/internal.h"
+#include "seclet.h"
+#include "libcoff.h"
+
+static asection bfd_debug_section = { "*DEBUG*" };
+
+/* Take a section header read from a coff file (in HOST byte order),
+ and make a BFD "section" out of it. This is used by ECOFF. */
+static boolean
+DEFUN(make_a_section_from_file,(abfd, hdr, target_index),
+ bfd *abfd AND
+ struct internal_scnhdr *hdr AND
+ unsigned int target_index)
+{
+ asection *return_section;
+ char *name;
+
+ /* Assorted wastage to null-terminate the name, thanks AT&T! */
+ name = bfd_alloc(abfd, sizeof (hdr->s_name)+1);
+ if (name == NULL) {
+ bfd_error = no_memory;
+ return false;
+ }
+ strncpy(name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
+ name[sizeof (hdr->s_name)] = 0;
+
+ return_section = bfd_make_section(abfd, name);
+ if (return_section == NULL)
+ return_section = bfd_coff_make_section_hook (abfd, name);
+
+ /* Handle several sections of the same name. For example, if an executable
+ has two .bss sections, GDB better be able to find both of them
+ (PR 3562). */
+ if (return_section == NULL)
+ return_section = bfd_make_section_anyway (abfd, name);
+
+ if (return_section == NULL)
+ return false;
+
+ /* s_paddr is presumed to be = to s_vaddr */
+
+ return_section->vma = hdr->s_vaddr;
+ return_section->_raw_size = hdr->s_size;
+ return_section->filepos = hdr->s_scnptr;
+ return_section->rel_filepos = hdr->s_relptr;
+ return_section->reloc_count = hdr->s_nreloc;
+
+ bfd_coff_set_alignment_hook (abfd, return_section, hdr);
+
+ return_section->line_filepos = hdr->s_lnnoptr;
+
+ return_section->lineno_count = hdr->s_nlnno;
+ return_section->userdata = NULL;
+ return_section->next = (asection *) NULL;
+ return_section->flags = bfd_coff_styp_to_sec_flags_hook (abfd, hdr);
+
+ return_section->target_index = target_index;
+
+ /* At least on i386-coff, the line number count for a shared library
+ section must be ignored. */
+ if ((return_section->flags & SEC_SHARED_LIBRARY) != 0)
+ return_section->lineno_count = 0;
+
+ if (hdr->s_nreloc != 0)
+ return_section->flags |= SEC_RELOC;
+ /* FIXME: should this check 'hdr->s_size > 0' */
+ if (hdr->s_scnptr != 0)
+ return_section->flags |= SEC_HAS_CONTENTS;
+ return true;
+}
+
+/* Read in a COFF object and make it into a BFD. This is used by
+ ECOFF as well. */
+
+static
+bfd_target *
+DEFUN(coff_real_object_p,(abfd, nscns, internal_f, internal_a),
+ bfd *abfd AND
+ unsigned nscns AND
+ struct internal_filehdr *internal_f AND
+ struct internal_aouthdr *internal_a)
+{
+ PTR tdata;
+ size_t readsize; /* length of file_info */
+ unsigned int scnhsz;
+ char *external_sections;
+
+ /* Build a play area */
+ tdata = bfd_coff_mkobject_hook (abfd, (PTR) internal_f, (PTR) internal_a);
+ if (tdata == NULL)
+ return 0;
+
+ scnhsz = bfd_coff_scnhsz (abfd);
+ readsize = nscns * scnhsz;
+ external_sections = (char *)bfd_alloc(abfd, readsize);
+
+ if (bfd_read((PTR)external_sections, 1, readsize, abfd) != readsize) {
+ goto fail;
+ }
+
+ /* Now copy data as required; construct all asections etc */
+ if (nscns != 0) {
+ unsigned int i;
+ for (i = 0; i < nscns; i++) {
+ struct internal_scnhdr tmp;
+ bfd_coff_swap_scnhdr_in(abfd, (PTR) (external_sections + i * scnhsz),
+ (PTR) &tmp);
+ make_a_section_from_file(abfd,&tmp, i+1);
+ }
+ }
+
+/* make_abs_section(abfd);*/
+
+ if (bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f) == false)
+ goto fail;
+
+ if (!(internal_f->f_flags & F_RELFLG))
+ abfd->flags |= HAS_RELOC;
+ if ((internal_f->f_flags & F_EXEC))
+ abfd->flags |= EXEC_P;
+ if (!(internal_f->f_flags & F_LNNO))
+ abfd->flags |= HAS_LINENO;
+ if (!(internal_f->f_flags & F_LSYMS))
+ abfd->flags |= HAS_LOCALS;
+
+
+ bfd_get_symcount(abfd) = internal_f->f_nsyms;
+ if (internal_f->f_nsyms)
+ abfd->flags |= HAS_SYMS;
+
+ if (internal_a != (struct internal_aouthdr *) NULL)
+ bfd_get_start_address (abfd) = internal_a->entry;
+ else
+ bfd_get_start_address (abfd) = 0;
+
+ return abfd->xvec;
+ fail:
+ bfd_release(abfd, tdata);
+ return (bfd_target *)NULL;
+}
+
+/* Turn a COFF file into a BFD, but fail with wrong_format if it is
+ not a COFF file. This is also used by ECOFF. */
+
+bfd_target *
+DEFUN(coff_object_p,(abfd),
+ bfd *abfd)
+{
+ unsigned int filhsz;
+ unsigned int aoutsz;
+ int nscns;
+ PTR filehdr;
+ struct internal_filehdr internal_f;
+ struct internal_aouthdr internal_a;
+
+ bfd_error = system_call_error;
+
+ /* figure out how much to read */
+ filhsz = bfd_coff_filhsz (abfd);
+ aoutsz = bfd_coff_aoutsz (abfd);
+
+ filehdr = bfd_alloc (abfd, filhsz);
+ if (filehdr == NULL)
+ return 0;
+ if (bfd_read(filehdr, 1, filhsz, abfd) != filhsz)
+ return 0;
+ bfd_coff_swap_filehdr_in(abfd, filehdr, &internal_f);
+ bfd_release (abfd, filehdr);
+
+ if (bfd_coff_bad_format_hook (abfd, &internal_f) == false) {
+ bfd_error = wrong_format;
+ return 0;
+ }
+ nscns =internal_f.f_nscns;
+
+ if (internal_f.f_opthdr) {
+ PTR opthdr;
+
+ opthdr = bfd_alloc (abfd, aoutsz);
+ if (opthdr == NULL)
+ return 0;;
+ if (bfd_read(opthdr, 1,aoutsz, abfd) != aoutsz) {
+ return 0;
+ }
+ bfd_coff_swap_aouthdr_in(abfd, opthdr, (PTR)&internal_a);
+ }
+
+ /* Seek past the opt hdr stuff */
+ bfd_seek(abfd, (file_ptr) (internal_f.f_opthdr + filhsz), SEEK_SET);
+
+ return coff_real_object_p(abfd, nscns, &internal_f,
+ (internal_f.f_opthdr != 0
+ ? &internal_a
+ : (struct internal_aouthdr *) NULL));
+}
+
+/* Get the BFD section from a COFF symbol section number. */
+
+struct sec *
+DEFUN(coff_section_from_bfd_index,(abfd, index),
+ bfd *abfd AND
+ int index)
+{
+ struct sec *answer = abfd->sections;
+
+ if (index == N_ABS)
+ {
+ return &bfd_abs_section;
+ }
+ if (index == N_UNDEF)
+ {
+ return &bfd_und_section;
+ }
+ if(index == N_DEBUG)
+ {
+ return &bfd_debug_section;
+
+ }
+
+ while (answer) {
+ if (answer->target_index == index)
+ return answer;
+ answer = answer->next;
+ }
+ BFD_ASSERT(0);
+ return &bfd_und_section; /* For gcc -W and lint. Never executed. */
+}
+
+/* Get the upper bound of a COFF symbol table. */
+
+unsigned int
+coff_get_symtab_upper_bound(abfd)
+bfd *abfd;
+{
+ if (!bfd_coff_slurp_symbol_table(abfd))
+ return 0;
+
+ return (bfd_get_symcount(abfd) + 1) * (sizeof(coff_symbol_type *));
+}
+
+
+/* Canonicalize a COFF symbol table. */
+
+unsigned int
+DEFUN(coff_get_symtab, (abfd, alocation),
+ bfd *abfd AND
+ asymbol **alocation)
+{
+ unsigned int counter = 0;
+ coff_symbol_type *symbase;
+ coff_symbol_type **location = (coff_symbol_type **) (alocation);
+ if (!bfd_coff_slurp_symbol_table(abfd))
+ return 0;
+
+ symbase = obj_symbols(abfd);
+ while (counter < bfd_get_symcount(abfd))
+ {
+ /* This nasty code looks at the symbol to decide whether or
+ not it is descibes a constructor/destructor entry point. It
+ is structured this way to (hopefully) speed non matches */
+#if 0
+ if (0 && symbase->symbol.name[9] == '$')
+ {
+ bfd_constructor_entry(abfd,
+ (asymbol **)location,
+ symbase->symbol.name[10] == 'I' ?
+ "CTOR" : "DTOR");
+ }
+#endif
+ *(location++) = symbase++;
+ counter++;
+ }
+ *location++ = 0;
+ return bfd_get_symcount(abfd);
+}
+
+/* Set lineno_count for the output sections of a COFF file. */
+
+int
+DEFUN(coff_count_linenumbers,(abfd),
+ bfd *abfd)
+{
+ unsigned int limit = bfd_get_symcount(abfd);
+ unsigned int i;
+ int total = 0;
+ 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 (bfd_asymbol_flavour(q_maybe) == bfd_target_coff_flavour) {
+ 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++;
+ total ++;
+ l++;
+ while (l->line_number) {
+ total ++;
+ q->symbol.section->output_section->lineno_count++;
+ l++;
+ }
+ }
+ }
+ }
+ return total;
+}
+
+/* Takes a bfd and a symbol, returns a pointer to the coff specific
+ area of the symbol if there is one. */
+
+coff_symbol_type *
+DEFUN(coff_symbol_from,(ignore_abfd, symbol),
+ bfd *ignore_abfd AND
+ asymbol *symbol)
+{
+ if (bfd_asymbol_flavour(symbol) != bfd_target_coff_flavour)
+ return (coff_symbol_type *)NULL;
+
+ if (bfd_asymbol_bfd(symbol)->tdata.coff_obj_data == (coff_data_type*)NULL)
+ return (coff_symbol_type *)NULL;
+
+ return (coff_symbol_type *) symbol;
+}
+
+static void
+DEFUN(fixup_symbol_value,(coff_symbol_ptr, syment),
+coff_symbol_type *coff_symbol_ptr AND
+struct internal_syment *syment)
+{
+
+ /* Normalize the symbol flags */
+ if (bfd_is_com_section (coff_symbol_ptr->symbol.section)) {
+ /* 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.section == & bfd_und_section) {
+ syment->n_scnum = N_UNDEF;
+ syment->n_value = 0;
+ }
+ else {
+ if (coff_symbol_ptr->symbol.section) {
+ syment->n_scnum =
+ coff_symbol_ptr->symbol.section->output_section->target_index;
+
+ syment->n_value =
+ coff_symbol_ptr->symbol.value +
+ coff_symbol_ptr->symbol.section->output_offset +
+ coff_symbol_ptr->symbol.section->output_section->vma;
+ }
+ else {
+ BFD_ASSERT(0);
+ /* This can happen, but I don't know why yet (steve@cygnus.com) */
+ syment->n_scnum = N_ABS;
+ syment->n_value = coff_symbol_ptr->symbol.value;
+ }
+ }
+}
+
+/* run through all the symbols in the symbol table and work out what
+ their indexes into the symbol table will be when output
+
+ Coff requires that each C_FILE symbol points to the next one in the
+ chain, and that the last one points to the first external symbol. We
+ do that here too.
+
+*/
+void
+DEFUN(coff_renumber_symbols,(bfd_ptr),
+ bfd *bfd_ptr)
+{
+ unsigned int symbol_count = bfd_get_symcount(bfd_ptr);
+ asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols;
+ unsigned int native_index = 0;
+ struct internal_syment *last_file = (struct internal_syment *)NULL;
+ unsigned int symbol_index;
+
+ /* COFF demands that undefined symbols come after all other symbols.
+ Since we don't need to impose this extra knowledge on all our client
+ programs, deal with that here. Sort the symbol table; just move the
+ undefined symbols to the end, leaving the rest alone. */
+ /* @@ Do we have some condition we could test for, so we don't always
+ have to do this? I don't think relocatability is quite right, but
+ I'm not certain. [raeburn:19920508.1711EST] */
+ {
+ asymbol **newsyms;
+ int i;
+
+ newsyms = (asymbol **) bfd_alloc_by_size_t (bfd_ptr,
+ sizeof (asymbol *)
+ * (symbol_count + 1));
+ bfd_ptr->outsymbols = newsyms;
+ for (i = 0; i < symbol_count; i++)
+ if (symbol_ptr_ptr[i]->section != &bfd_und_section)
+ *newsyms++ = symbol_ptr_ptr[i];
+ for (i = 0; i < symbol_count; i++)
+ if (symbol_ptr_ptr[i]->section == &bfd_und_section)
+ *newsyms++ = symbol_ptr_ptr[i];
+ *newsyms = (asymbol *) NULL;
+ symbol_ptr_ptr = bfd_ptr->outsymbols;
+ }
+
+ 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_ptr->native) {
+ combined_entry_type *s = coff_symbol_ptr->native;
+ int i;
+
+ if (s->u.syment.n_sclass == C_FILE)
+ {
+ if (last_file != (struct internal_syment *)NULL) {
+ last_file->n_value = native_index;
+ }
+ last_file = &(s->u.syment);
+ }
+ else {
+
+ /* Modify the symbol values according to their section and
+ type */
+
+ fixup_symbol_value(coff_symbol_ptr, &(s->u.syment));
+ }
+ for (i = 0; i < s->u.syment.n_numaux + 1; i++) {
+ s[i].offset = native_index ++;
+ }
+ }
+ else {
+ native_index++;
+ }
+ }
+ obj_conv_table_size (bfd_ptr) = native_index;
+}
+
+/*
+ Run thorough the symbol table again, and fix it so that all pointers to
+ entries are changed to the entries' index in the output symbol table.
+
+*/
+void
+DEFUN(coff_mangle_symbols,(bfd_ptr),
+ bfd *bfd_ptr)
+{
+ unsigned int symbol_count = bfd_get_symcount(bfd_ptr);
+ asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols;
+ unsigned int symbol_index;
+
+ 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_ptr->native) {
+ int i;
+ combined_entry_type *s = coff_symbol_ptr->native;
+
+ for (i = 0; i < s->u.syment.n_numaux ; i++) {
+ combined_entry_type *a = s + i + 1;
+ if (a->fix_tag) {
+ a->u.auxent.x_sym.x_tagndx.l =
+ a->u.auxent.x_sym.x_tagndx.p->offset;
+ a->fix_tag = 0;
+ }
+ if (a->fix_end) {
+ a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l =
+ a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset;
+ a->fix_end = 0;
+
+ }
+
+ }
+ }
+ }
+}
+
+static int string_size;
+
+static void
+DEFUN(coff_fix_symbol_name,(abfd, symbol, native),
+ bfd *abfd AND
+ asymbol *symbol AND
+ combined_entry_type *native)
+{
+ unsigned int name_length;
+ union internal_auxent *auxent;
+ char * name = ( char *)(symbol->name);
+
+ if (name == (char *) NULL) {
+ /* coff symbols always have names, so we'll make one up */
+ symbol->name = "strange";
+ name = (char *)symbol->name;
+ }
+ name_length = strlen(name);
+
+ if (native->u.syment.n_sclass == C_FILE) {
+ strncpy(native->u.syment._n._n_name, ".file", SYMNMLEN);
+ auxent = &(native+1)->u.auxent;
+
+ if (bfd_coff_long_filenames (abfd)) {
+ if (name_length <= FILNMLEN) {
+ strncpy(auxent->x_file.x_fname, name, FILNMLEN);
+ }
+ else {
+ auxent->x_file.x_n.x_offset = string_size + 4;
+ auxent->x_file.x_n.x_zeroes = 0;
+ string_size += name_length + 1;
+ }
+ }
+ else {
+ strncpy(auxent->x_file.x_fname, name, FILNMLEN);
+ if (name_length > FILNMLEN) {
+ name[FILNMLEN] = '\0';
+ }
+ }
+ }
+ else
+ { /* NOT A C_FILE SYMBOL */
+ if (name_length <= SYMNMLEN) {
+ /* This name will fit into the symbol neatly */
+ strncpy(native->u.syment._n._n_name, symbol->name, SYMNMLEN);
+ }
+ else {
+ native->u.syment._n._n_n._n_offset = string_size + 4;
+ native->u.syment._n._n_n._n_zeroes = 0;
+ string_size += name_length + 1;
+ }
+ }
+}
+
+#define set_index(symbol, idx) ((symbol)->udata =(PTR) (idx))
+
+static unsigned int
+DEFUN(coff_write_symbol,(abfd, symbol, native, written),
+bfd *abfd AND
+asymbol *symbol AND
+combined_entry_type *native AND
+unsigned int written)
+{
+ unsigned int numaux = native->u.syment.n_numaux;
+ int type = native->u.syment.n_type;
+ int class = native->u.syment.n_sclass;
+ PTR buf;
+ bfd_size_type symesz;
+
+ /* @@ bfd_debug_section isn't accessible outside this file, but we know
+ that C_FILE symbols belong there. So move them. */
+ if (native->u.syment.n_sclass == C_FILE)
+ symbol->section = &bfd_debug_section;
+
+ if (symbol->section == &bfd_abs_section)
+ {
+ native->u.syment.n_scnum = N_ABS;
+ }
+ else if (symbol->section == &bfd_debug_section)
+ {
+ native->u.syment.n_scnum = N_DEBUG;
+ }
+ else if (symbol->section == &bfd_und_section)
+ {
+ native->u.syment.n_scnum = N_UNDEF;
+ }
+ else
+ {
+ native->u.syment.n_scnum =
+ symbol->section->output_section->target_index;
+ }
+
+
+ coff_fix_symbol_name(abfd, symbol, native);
+
+ symesz = bfd_coff_symesz (abfd);
+ buf = bfd_alloc (abfd, symesz);
+ bfd_coff_swap_sym_out(abfd, &native->u.syment, buf);
+ bfd_write(buf, 1, symesz, abfd);
+ bfd_release (abfd, buf);
+
+ if (native->u.syment.n_numaux > 0)
+ {
+ bfd_size_type auxesz;
+ unsigned int j;
+
+ auxesz = bfd_coff_auxesz (abfd);
+ buf = bfd_alloc (abfd, auxesz);
+ for (j = 0; j < native->u.syment.n_numaux; j++)
+ {
+ bfd_coff_swap_aux_out(abfd,
+ &((native + j + 1)->u.auxent),
+ type,
+ class,
+ buf);
+ bfd_write(buf, 1, auxesz, abfd);
+ }
+ bfd_release (abfd, buf);
+ }
+ /*
+ Reuse somewhere in the symbol to keep the index
+ */
+ set_index(symbol, written);
+ return written + 1 + numaux;
+}
+
+
+static unsigned int
+DEFUN(coff_write_alien_symbol,(abfd, symbol, written),
+ bfd *abfd AND
+ asymbol *symbol AND
+ unsigned int written)
+{
+ /*
+ 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
+ */
+ combined_entry_type *native;
+ combined_entry_type dummy;
+ native = &dummy;
+ native->u.syment.n_type = T_NULL;
+ native->u.syment.n_flags = 0;
+ if (symbol->section == &bfd_und_section)
+ {
+ native->u.syment.n_scnum = N_UNDEF;
+ native->u.syment.n_value = symbol->value;
+ }
+ else if (bfd_is_com_section (symbol->section))
+ {
+ native->u.syment.n_scnum = N_UNDEF;
+ native->u.syment.n_value = symbol->value;
+
+ }
+
+ else if (symbol->flags & BSF_DEBUGGING) {
+ /*
+ remove name so it doesn't take up any space
+ */
+ symbol->name = "";
+ }
+ else {
+ native->u.syment.n_scnum = symbol->section->output_section->target_index;
+ native->u.syment.n_value = symbol->value +
+ symbol->section->output_section->vma +
+ symbol->section->output_offset;
+ /* 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->u.syment.n_flags = bfd_asymbol_bfd(&c->symbol)->flags;
+ }
+ }
+ }
+
+ native->u.syment.n_type = 0;
+ if (symbol->flags & BSF_LOCAL)
+ native->u.syment.n_sclass = C_STAT;
+ else
+ native->u.syment.n_sclass = C_EXT;
+ native->u.syment.n_numaux = 0;
+
+ return coff_write_symbol(abfd, symbol, native, written);
+}
+
+static unsigned int
+DEFUN(coff_write_native_symbol,(abfd, symbol, written),
+bfd *abfd AND
+coff_symbol_type *symbol AND
+unsigned int written)
+{
+ /*
+ 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
+ */
+ combined_entry_type *native = symbol->native;
+
+ alent *lineno = symbol->lineno;
+
+ if (lineno && !symbol->done_lineno) {
+ unsigned int count = 0;
+ lineno[count].u.offset = written;
+ if (native->u.syment.n_numaux) {
+ union internal_auxent *a = &((native+1)->u.auxent);
+
+ a->x_sym.x_fcnary.x_fcn.x_lnnoptr =
+ symbol->symbol.section->output_section->moving_line_filepos;
+ }
+ /*
+ And count and relocate all other linenumbers
+ */
+
+ count++;
+ while (lineno[count].line_number) {
+#if 0
+/* 13 april 92. sac
+I've been told this, but still need proof:
+> The second bug is also in `bfd/coffcode.h'. This bug causes the linker to screw
+> up the pc-relocations for all the line numbers in COFF code. This bug isn't
+> only specific to A29K implementations, but affects all systems using COFF
+> format binaries. Note that in COFF object files, the line number core offsets
+> output by the assembler are relative to the start of each procedure, not
+> to the start of the .text section. This patch relocates the line numbers
+> relative to the `native->u.syment.n_value' instead of the section virtual
+> address. modular!olson@cs.arizona.edu (Jon Olson)
+*/
+ lineno[count].u.offset += native->u.syment.n_value;
+
+#else
+ lineno[count].u.offset +=
+ symbol->symbol.section->output_section->vma +
+ symbol->symbol.section->output_offset;
+#endif
+ count++;
+ }
+ symbol->done_lineno = true;
+
+ symbol->symbol.section->output_section->moving_line_filepos +=
+ count * bfd_coff_linesz (abfd);
+ }
+ return coff_write_symbol(abfd, &( symbol->symbol), native,written);
+}
+
+void
+DEFUN(coff_write_symbols,(abfd),
+ bfd *abfd)
+{
+ unsigned int i;
+ unsigned int limit = bfd_get_symcount(abfd);
+ unsigned int written = 0;
+
+ asymbol **p;
+
+ 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);
+
+ if (c_symbol == (coff_symbol_type *) NULL ||
+ c_symbol->native == (combined_entry_type *)NULL)
+ {
+ written = coff_write_alien_symbol(abfd, symbol, written);
+ }
+ else
+ {
+ written = coff_write_native_symbol(abfd, c_symbol, written);
+ }
+
+ }
+
+ bfd_get_symcount(abfd) = written;
+
+ /* Now write out strings */
+
+ if (string_size != 0)
+ {
+ unsigned int size = string_size + 4;
+ bfd_byte buffer[4];
+
+ bfd_h_put_32(abfd, size, buffer);
+ bfd_write((PTR) buffer, 1, sizeof(buffer), abfd);
+ for (p = abfd->outsymbols, i = 0;
+ i < limit;
+ i++, p++)
+ {
+ asymbol *q = *p;
+ size_t name_length = strlen(q->name);
+ int maxlen;
+ coff_symbol_type* c_symbol = coff_symbol_from(abfd, q);
+ maxlen = ((c_symbol != NULL && c_symbol->native != NULL) &&
+ (c_symbol->native->u.syment.n_sclass == C_FILE)) ?
+ FILNMLEN : SYMNMLEN;
+
+ if (name_length > maxlen) {
+ bfd_write((PTR) (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. */
+ unsigned int size = 4;
+ bfd_byte buffer[4];
+
+ bfd_h_put_32 (abfd, size, buffer);
+ bfd_write((PTR) buffer, 1, sizeof (buffer), abfd);
+ }
+}
+
+void
+DEFUN(coff_write_linenumbers,(abfd),
+ bfd *abfd)
+{
+ asection *s;
+ bfd_size_type linesz;
+ PTR buff;
+
+ linesz = bfd_coff_linesz (abfd);
+ buff = bfd_alloc (abfd, linesz);
+ 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;
+ if (p->section->output_section == s) {
+ alent *l =
+ BFD_SEND(bfd_asymbol_bfd(p), _get_lineno, (bfd_asymbol_bfd(p), p));
+ if (l) {
+ /* Found a linenumber entry, output */
+ struct internal_lineno out;
+ memset( (PTR)&out, 0, sizeof(out));
+ out.l_lnno = 0;
+ out.l_addr.l_symndx = l->u.offset;
+ bfd_coff_swap_lineno_out(abfd, &out, buff);
+ bfd_write(buff, 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_out(abfd, &out, buff);
+ bfd_write(buff, 1, linesz, abfd);
+ l++;
+ }
+ }
+ }
+ q++;
+ }
+ }
+ }
+ bfd_release (abfd, buff);
+}
+
+alent *
+DEFUN(coff_get_lineno,(ignore_abfd, symbol),
+ bfd *ignore_abfd AND
+ asymbol *symbol)
+{
+ return coffsymbol(symbol)->lineno;
+}
+
+asymbol *
+coff_section_symbol (abfd, name)
+ bfd *abfd;
+ char *name;
+{
+ asection *sec = bfd_make_section_old_way (abfd, name);
+ asymbol *sym;
+ combined_entry_type *csym;
+
+ sym = sec->symbol;
+ csym = coff_symbol_from (abfd, sym)->native;
+ /* Make sure back-end COFF stuff is there. */
+ if (csym == 0)
+ {
+ struct foo {
+ coff_symbol_type sym;
+ /* @@FIXME This shouldn't use a fixed size!! */
+ combined_entry_type e[10];
+ };
+ struct foo *f;
+ f = (struct foo *) bfd_alloc_by_size_t (abfd, sizeof (*f));
+ memset ((char *) f, 0, sizeof (*f));
+ coff_symbol_from (abfd, sym)->native = csym = f->e;
+ }
+ csym[0].u.syment.n_sclass = C_STAT;
+ csym[0].u.syment.n_numaux = 1;
+/* SF_SET_STATICS (sym); @@ ??? */
+ csym[1].u.auxent.x_scn.x_scnlen = sec->_raw_size;
+ csym[1].u.auxent.x_scn.x_nreloc = sec->reloc_count;
+ csym[1].u.auxent.x_scn.x_nlinno = sec->lineno_count;
+
+ if (sec->output_section == NULL)
+ {
+ sec->output_section = sec;
+ sec->output_offset = 0;
+ }
+
+ return sym;
+}
+
+/* This function transforms the offsets into the symbol table into
+ pointers to syments. */
+
+static void
+DEFUN(coff_pointerize_aux,(abfd, table_base, type, class, auxent),
+bfd *abfd AND
+combined_entry_type *table_base AND
+int type AND
+int class AND
+combined_entry_type *auxent)
+{
+ /* Don't bother if this is a file or a section */
+ if (class == C_STAT && type == T_NULL) return;
+ if (class == C_FILE) return;
+
+ /* Otherwise patch up */
+#define N_TMASK coff_data (abfd)->local_n_tmask
+#define N_BTSHFT coff_data (abfd)->local_n_btshft
+ if (ISFCN(type) || ISTAG(class) || class == C_BLOCK) {
+ auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = table_base +
+ auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l;
+ auxent->fix_end = 1;
+ }
+ /* A negative tagndx is meaningless, but the SCO 3.2v4 cc can
+ generate one, so we must be careful to ignore it. */
+ if (auxent->u.auxent.x_sym.x_tagndx.l > 0) {
+ auxent->u.auxent.x_sym.x_tagndx.p =
+ table_base + auxent->u.auxent.x_sym.x_tagndx.l;
+ auxent->fix_tag = 1;
+ }
+}
+
+static char *
+DEFUN(build_string_table,(abfd),
+bfd *abfd)
+{
+ char string_table_size_buffer[4];
+ unsigned int string_table_size;
+ char *string_table;
+
+ /* 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_buffer,
+ sizeof(string_table_size_buffer),
+ 1, abfd) != sizeof(string_table_size)) {
+ bfd_error = system_call_error;
+ return (NULL);
+ } /* on error */
+
+ string_table_size = bfd_h_get_32(abfd, (bfd_byte *) string_table_size_buffer);
+
+ if ((string_table = (PTR) bfd_alloc(abfd, 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);
+ }
+ return string_table;
+}
+
+/* Allocate space for the ".debug" section, and read it.
+ We did not read the debug section until now, because
+ we didn't want to go to the trouble until someone needed it. */
+
+static char *
+DEFUN(build_debug_section,(abfd),
+ bfd *abfd)
+{
+ char *debug_section;
+ long position;
+
+ asection *sect = bfd_get_section_by_name (abfd, ".debug");
+
+ if (!sect) {
+ bfd_error = no_debug_section;
+ return NULL;
+ }
+
+ debug_section = (PTR) bfd_alloc (abfd,
+ bfd_get_section_size_before_reloc (sect));
+ if (debug_section == NULL) {
+ bfd_error = no_memory;
+ return NULL;
+ }
+
+ /* Seek to the beginning of the `.debug' section and read it.
+ Save the current position first; it is needed by our caller.
+ Then read debug section and reset the file pointer. */
+
+ position = bfd_tell (abfd);
+ bfd_seek (abfd, sect->filepos, SEEK_SET);
+ if (bfd_read (debug_section,
+ bfd_get_section_size_before_reloc (sect), 1, abfd)
+ != bfd_get_section_size_before_reloc(sect)) {
+ bfd_error = system_call_error;
+ return NULL;
+ }
+ bfd_seek (abfd, position, SEEK_SET);
+ return debug_section;
+}
+
+
+/* Return a pointer to a malloc'd copy of 'name'. 'name' may not be
+ \0-terminated, but will not exceed 'maxlen' characters. The copy *will*
+ be \0-terminated. */
+static char *
+DEFUN(copy_name,(abfd, name, maxlen),
+ bfd *abfd AND
+ char *name AND
+ int maxlen)
+{
+ int len;
+ char *newname;
+
+ for (len = 0; len < maxlen; ++len) {
+ if (name[len] == '\0') {
+ break;
+ }
+ }
+
+ if ((newname = (PTR) bfd_alloc(abfd, len+1)) == NULL) {
+ bfd_error = no_memory;
+ return (NULL);
+ }
+ strncpy(newname, name, len);
+ newname[len] = '\0';
+ return newname;
+}
+
+/* Read a symbol table into freshly bfd_allocated 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. */
+
+combined_entry_type *
+DEFUN(coff_get_normalized_symtab,(abfd),
+bfd *abfd)
+{
+ combined_entry_type *internal;
+ combined_entry_type *internal_ptr;
+ combined_entry_type *symbol_ptr;
+ combined_entry_type *internal_end;
+ bfd_size_type symesz;
+ PTR raw;
+ char *raw_src;
+ char *raw_end;
+ char *string_table = NULL;
+ char *debug_section = NULL;
+ unsigned long size;
+
+ unsigned int raw_size;
+ if (obj_raw_syments(abfd) != (combined_entry_type *)NULL) {
+ return obj_raw_syments(abfd);
+ }
+ if ((size = bfd_get_symcount(abfd) * sizeof(combined_entry_type)) == 0) {
+ bfd_error = no_symbols;
+ return (NULL);
+ }
+
+ internal = (combined_entry_type *)bfd_alloc(abfd, size);
+ internal_end = internal + bfd_get_symcount(abfd);
+
+ symesz = bfd_coff_symesz (abfd);
+ raw_size = bfd_get_symcount(abfd) * symesz;
+ raw = bfd_alloc(abfd,raw_size);
+
+ if (bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET) == -1
+ || bfd_read(raw, raw_size, 1, abfd) != raw_size) {
+ bfd_error = system_call_error;
+ return (NULL);
+ }
+ /* mark the end of the symbols */
+ raw_end = (char *) raw + bfd_get_symcount(abfd) * symesz;
+ /*
+ FIXME SOMEDAY. A string table size of zero is very weird, but
+ probably possible. If one shows up, it will probably kill us.
+ */
+
+ /* Swap all the raw entries */
+ for (raw_src = (char *) raw, internal_ptr = internal;
+ raw_src < raw_end;
+ raw_src += symesz, internal_ptr++) {
+
+ unsigned int i;
+ bfd_coff_swap_sym_in(abfd, (PTR)raw_src, (PTR)&internal_ptr->u.syment);
+ internal_ptr->fix_tag = 0;
+ internal_ptr->fix_end = 0;
+ symbol_ptr = internal_ptr;
+
+ for (i = 0;
+ i < symbol_ptr->u.syment.n_numaux;
+ i++)
+ {
+ internal_ptr++;
+ raw_src += symesz;
+
+ internal_ptr->fix_tag = 0;
+ internal_ptr->fix_end = 0;
+ bfd_coff_swap_aux_in(abfd, (PTR) raw_src,
+ symbol_ptr->u.syment.n_type,
+ symbol_ptr->u.syment.n_sclass,
+ &(internal_ptr->u.auxent));
+ /* Remember that bal entries arn't pointerized */
+ if (i != 1 || symbol_ptr->u.syment.n_sclass != C_LEAFPROC)
+ {
+
+ coff_pointerize_aux(abfd,
+ internal,
+ symbol_ptr->u.syment.n_type,
+ symbol_ptr->u.syment.n_sclass,
+ internal_ptr);
+ }
+
+ }
+ }
+
+ /* Free all the raw stuff */
+ bfd_release(abfd, raw);
+
+ for (internal_ptr = internal; internal_ptr < internal_end;
+ internal_ptr ++)
+ {
+ if (internal_ptr->u.syment.n_sclass == C_FILE) {
+ /* make a file symbol point to the name in the auxent, since
+ the text ".file" is redundant */
+ if ((internal_ptr+1)->u.auxent.x_file.x_n.x_zeroes == 0) {
+ /* the filename is a long one, point into the string table */
+ if (string_table == NULL) {
+ string_table = build_string_table(abfd);
+ }
+
+ internal_ptr->u.syment._n._n_n._n_offset =
+ (long) (string_table - 4 +
+ (internal_ptr+1)->u.auxent.x_file.x_n.x_offset);
+ }
+ else {
+ /* ordinary short filename, put into memory anyway */
+ internal_ptr->u.syment._n._n_n._n_offset = (long)
+ copy_name(abfd, (internal_ptr+1)->u.auxent.x_file.x_fname,
+ FILNMLEN);
+ }
+ }
+ else {
+ if (internal_ptr->u.syment._n._n_n._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 (internal_ptr->u.syment._n._n_name[i] == '\0') {
+ break;
+ } /* if end of string */
+ } /* possible lengths of this string. */
+
+ if ((newstring = (PTR) bfd_alloc(abfd, ++i)) == NULL) {
+ bfd_error = no_memory;
+ return (NULL);
+ } /* on error */
+ memset(newstring, 0, i);
+ strncpy(newstring, internal_ptr->u.syment._n._n_name, i-1);
+ internal_ptr->u.syment._n._n_n._n_offset = (long int) newstring;
+ internal_ptr->u.syment._n._n_n._n_zeroes = 0;
+ }
+ else if (!bfd_coff_symname_in_debug(abfd, &internal_ptr->u.syment)) {
+ /* Long name already. Point symbol at the string in the table. */
+ if (string_table == NULL) {
+ string_table = build_string_table(abfd);
+ }
+ internal_ptr->u.syment._n._n_n._n_offset = (long int)
+ (string_table - 4 + internal_ptr->u.syment._n._n_n._n_offset);
+ }
+ else {
+ /* Long name in debug section. Very similar. */
+ if (debug_section == NULL) {
+ debug_section = build_debug_section(abfd);
+ }
+ internal_ptr->u.syment._n._n_n._n_offset = (long int)
+ (debug_section + internal_ptr->u.syment._n._n_n._n_offset);
+ }
+ }
+ internal_ptr += internal_ptr->u.syment.n_numaux;
+ }
+
+ obj_raw_syments(abfd) = internal;
+ obj_raw_syment_count(abfd) = internal_ptr - internal;
+
+ return (internal);
+} /* coff_get_normalized_symtab() */
+
+unsigned int
+DEFUN (coff_get_reloc_upper_bound, (abfd, asect),
+ bfd *abfd AND
+ sec_ptr asect)
+{
+ if (bfd_get_format(abfd) != bfd_object) {
+ bfd_error = invalid_operation;
+ return 0;
+ }
+ return (asect->reloc_count + 1) * sizeof(arelent *);
+}
+
+asymbol *
+DEFUN (coff_make_empty_symbol, (abfd),
+ bfd *abfd)
+{
+ coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type));
+ if (new == NULL) {
+ bfd_error = no_memory;
+ return (NULL);
+ } /* on error */
+ new->symbol.section = 0;
+ new->native = 0;
+ new->lineno = (alent *) NULL;
+ new->done_lineno = false;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+/* Make a debugging symbol. */
+
+asymbol *
+coff_bfd_make_debug_symbol (abfd, ptr, sz)
+ bfd *abfd;
+ PTR ptr;
+ unsigned long sz;
+{
+ coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type));
+ if (new == NULL) {
+ bfd_error = no_memory;
+ return (NULL);
+ } /* on error */
+ /* @@ This shouldn't be using a constant multiplier. */
+ new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10);
+ new->symbol.section = &bfd_debug_section;
+ new->lineno = (alent *) NULL;
+ new->done_lineno = false;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+void
+coff_get_symbol_info (abfd, symbol, ret)
+ bfd *abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+/* Print out information about COFF symbol. */
+
+void
+coff_print_symbol (abfd, filep, symbol, how)
+ bfd *abfd;
+ PTR filep;
+ asymbol *symbol;
+ bfd_print_symbol_type how;
+{
+ FILE *file = (FILE *) filep;
+
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ fprintf (file, "%s", symbol->name);
+ break;
+
+ case bfd_print_symbol_more:
+ fprintf (file, "coff %s %s",
+ coffsymbol(symbol)->native ? "n" : "g",
+ coffsymbol(symbol)->lineno ? "l" : " ");
+ break;
+
+ case bfd_print_symbol_all:
+ if (coffsymbol(symbol)->native)
+ {
+ unsigned int aux;
+ combined_entry_type *combined = coffsymbol (symbol)->native;
+ combined_entry_type *root = obj_raw_syments (abfd);
+ struct lineno_cache_entry *l = coffsymbol(symbol)->lineno;
+
+ fprintf (file,"[%3d]", combined - root);
+
+ fprintf (file,
+ "(sc %2d)(fl 0x%02x)(ty %3x)(sc %3d) (nx %d) 0x%08x %s",
+ combined->u.syment.n_scnum,
+ combined->u.syment.n_flags,
+ combined->u.syment.n_type,
+ combined->u.syment.n_sclass,
+ combined->u.syment.n_numaux,
+ combined->u.syment.n_value,
+ symbol->name);
+
+ for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
+ {
+ combined_entry_type *auxp = combined + aux + 1;
+ long tagndx;
+
+ if (auxp->fix_tag)
+ tagndx = auxp->u.auxent.x_sym.x_tagndx.p - root;
+ else
+ tagndx = auxp->u.auxent.x_sym.x_tagndx.l;
+
+ fprintf (file, "\n");
+ switch (combined->u.syment.n_sclass)
+ {
+ case C_FILE:
+ fprintf (file, "File ");
+ break;
+ default:
+
+ fprintf (file, "AUX lnno %d size 0x%x tagndx %d",
+ auxp->u.auxent.x_sym.x_misc.x_lnsz.x_lnno,
+ auxp->u.auxent.x_sym.x_misc.x_lnsz.x_size,
+ tagndx);
+ break;
+ }
+ }
+
+ if (l)
+ {
+ fprintf (file, "\n%s :", l->u.sym->name);
+ l++;
+ while (l->line_number)
+ {
+ fprintf (file, "\n%4d : 0x%x",
+ l->line_number,
+ l->u.offset + symbol->section->vma);
+ l++;
+ }
+ }
+ }
+ else
+ {
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+ fprintf (file, " %-5s %s %s %s",
+ symbol->section->name,
+ coffsymbol(symbol)->native ? "n" : "g",
+ coffsymbol(symbol)->lineno ? "l" : " ",
+ symbol->name);
+ }
+ }
+}
+
+/* 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
+DEFUN(coff_find_nearest_line,(abfd,
+ section,
+ ignore_symbols,
+ offset,
+ filename_ptr,
+ functionname_ptr,
+ line_ptr),
+ bfd *abfd AND
+ asection *section AND
+ asymbol **ignore_symbols AND
+ bfd_vma offset AND
+ CONST char **filename_ptr AND
+ CONST char **functionname_ptr AND
+ unsigned int *line_ptr)
+{
+ static bfd *cache_abfd;
+ static asection *cache_section;
+ static bfd_vma cache_offset;
+ static unsigned int cache_i;
+ static CONST char *cache_function;
+ static unsigned int line_base = 0;
+
+ unsigned int i = 0;
+ coff_data_type *cof = coff_data(abfd);
+ /* Run through the raw syments if available */
+ combined_entry_type *p;
+ alent *l;
+
+
+ *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)
+ return false;
+
+ if (cof == NULL)
+ return false;
+
+ p = cof->raw_syments;
+
+ for (i = 0; i < cof->raw_syment_count; i++) {
+ if (p->u.syment.n_sclass == C_FILE) {
+ /* File name has been moved into symbol */
+ *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
+ break;
+ }
+ p += 1 + p->u.syment.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;
+ *functionname_ptr = cache_function;
+ }
+ else {
+ i = 0;
+ }
+ l = &section->lineno[i];
+
+ 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);
+ if (coff->symbol.value > offset)
+ break;
+ *functionname_ptr = coff->symbol.name;
+ if (coff->native) {
+ combined_entry_type *s = coff->native;
+ s = s + 1 + s->u.syment.n_numaux;
+ /*
+ S should now point to the .bf of the function
+ */
+ if (s->u.syment.n_numaux) {
+ /*
+ The linenumber is stored in the auxent
+ */
+ union internal_auxent *a = &((s + 1)->u.auxent);
+ line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
+ *line_ptr = line_base;
+ }
+ }
+ }
+ 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_function = *functionname_ptr;
+
+ return true;
+}
+
+int
+DEFUN(coff_sizeof_headers,(abfd, reloc),
+ bfd *abfd AND
+ boolean reloc)
+{
+ size_t size;
+
+ if (reloc == false) {
+ size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
+ }
+ else {
+ size = bfd_coff_filhsz (abfd);
+ }
+
+ size += abfd->section_count * bfd_coff_scnhsz (abfd);
+ return size;
+}
diff --git a/gnu/usr.bin/gdb/bfd/core.c b/gnu/usr.bin/gdb/bfd/core.c
new file mode 100644
index 000000000000..c428775fbf3f
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/core.c
@@ -0,0 +1,106 @@
+/* Core file generic interface routines for BFD.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ Core files
+
+DESCRIPTION
+ Buff output this facinating topic
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+/*
+FUNCTION
+ bfd_core_file_failing_command
+
+SYNOPSIS
+ CONST char *bfd_core_file_failing_command(bfd *);
+
+DESCRIPTION
+ Returns a read-only string explaining what program was running
+ when it failed and produced the core file being read
+
+*/
+
+CONST char *
+DEFUN(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));
+}
+
+/*
+FUNCTION
+ bfd_core_file_failing_signal
+
+SYNOPSIS
+ int bfd_core_file_failing_signal(bfd *);
+
+DESCRIPTION
+ Returns the signal number which caused the core dump which
+ generated the file the BFD is attached to.
+*/
+
+int
+bfd_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ if (abfd->format != bfd_core) {
+ bfd_error = invalid_operation;
+ return 0;
+ }
+ return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
+}
+
+
+/*
+FUNCTION
+ core_file_matches_executable_p
+
+SYNOPSIS
+ boolean core_file_matches_executable_p
+ (bfd *core_bfd, bfd *exec_bfd);
+
+DESCRIPTION
+ Returns <<true>> if the core file attached to @var{core_bfd}
+ was generated by a run of the executable file attached to
+ @var{exec_bfd}, or else <<false>>.
+*/
+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));
+}
diff --git a/gnu/usr.bin/gdb/bfd/cpu-i386.c b/gnu/usr.bin/gdb/bfd/cpu-i386.c
new file mode 100644
index 000000000000..b4afdb2392bb
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/cpu-i386.c
@@ -0,0 +1,43 @@
+/* BFD support for the Intel 386 architecture.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+static bfd_arch_info_type arch_info_struct =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_i386,
+ 0, /* only 1 machine */
+ "i386",
+ "i386",
+ 3,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
+
+void DEFUN_VOID(bfd_i386_arch)
+{
+ bfd_arch_linkin(&arch_info_struct);
+}
diff --git a/gnu/usr.bin/gdb/bfd/ctor.c b/gnu/usr.bin/gdb/bfd/ctor.c
new file mode 100644
index 000000000000..adc69195ff6a
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/ctor.c
@@ -0,0 +1,148 @@
+/* BFD library support routines for constructors
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+
+ Hacked by Steve Chamberlain of Cygnus Support. With some help from
+ Judy Chamberlain too.
+
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ Constructors
+
+ Classes in C++ have `constructors' and `destructors'. These
+ are functions which are called automatically by the language
+ whenever data of a class is created or destroyed. Class data
+ which is static data may also be have a type which requires
+ `construction', the contructor must be called before the data
+ can be referenced, so the contructor must be called before the
+ program begins.
+
+ The common solution to this problem is for the compiler to
+ call a magic function as the first statement <<main>>.
+ This magic function, (often called <<__main>>) runs around
+ calling the constructors for all the things needing it.
+
+ With COFF the compile has a bargain with the linker et al.
+ All constructors are given strange names, for example
+ <<__GLOBAL__$I$foo>> might be the label of a contructor for
+ the class @var{foo}. The solution on unfortunate systems
+ (most system V machines) is to perform a partial link on all
+ the <<.o>> files, do an <<nm>> on the result, run <<awk>> or some
+ such over the result looking for strange <<__GLOBAL__$>>
+ symbols, generate a C program from this, compile it and link
+ with the partially linked input. This process is usually
+ called <<collect>>.
+
+ Some versions of <<a.out>> use something called the
+ <<set_vector>> mechanism. The constructor symbols are output
+ from the compiler with a special stab code saying that they
+ are constructors, and the linker can deal with them directly.
+
+ BFD allows applications (ie the linker) to deal with
+ constructor information independently of their external
+ implimentation by providing a set of entry points for the
+ indiviual object back ends to call which maintains a database
+ of the contructor information. The application can
+ interrogate the database to find out what it wants. The
+ construction data essential for the linker to be able to
+ perform its job are:
+
+ o asymbol -
+ The asymbol of the contructor entry point contains all the
+ information necessary to call the function.
+
+ o table id -
+ The type of symbol, i.e., is it a constructor, a destructor or
+ something else someone dreamed up to make our lives difficult.
+
+ This module takes this information and then builds extra
+ sections attached to the bfds which own the entry points. It
+ creates these sections as if they were tables of pointers to
+ the entry points, and builds relocation entries to go with
+ them so that the tables can be relocated along with the data
+ they reference.
+
+ These sections are marked with a special bit
+ (<<SEC_CONSTRUCTOR>>) which the linker notices and do with
+ what it wants.
+
+*/
+
+#include <bfd.h>
+#include <sysdep.h>
+#include <libbfd.h>
+
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_constructor_entry
+
+SYNOPSIS
+ void bfd_constructor_entry(bfd *abfd,
+ asymbol **symbol_ptr_ptr,
+ CONST char*type);
+
+
+DESCRIPTION
+ This function is called with an a symbol describing the
+ function to be called, an string which descibes the xtor type,
+ e.g., something like "CTOR" or "DTOR" would be fine. And the bfd
+ which owns the function. Its duty is to create a section
+ called "CTOR" or "DTOR" or whatever if the bfd doesn't already
+ have one, and grow a relocation table for the entry points as
+ they accumulate.
+
+*/
+
+
+void DEFUN(bfd_constructor_entry,(abfd, symbol_ptr_ptr, type),
+ bfd *abfd AND
+ asymbol **symbol_ptr_ptr AND
+ CONST char *type)
+
+{
+ /* Look up the section we're using to store the table in */
+ asection *rel_section = bfd_get_section_by_name (abfd, type);
+ if (rel_section == (asection *)NULL) {
+ rel_section = bfd_make_section (abfd, type);
+ rel_section->flags = SEC_CONSTRUCTOR;
+ rel_section->alignment_power = 2;
+ }
+
+ /* Create a relocation into the section which references the entry
+ point */
+ {
+ arelent_chain *reloc = (arelent_chain *)bfd_alloc(abfd,
+ sizeof(arelent_chain));
+
+/* reloc->relent.section = (asection *)NULL;*/
+ reloc->relent.addend = 0;
+
+ reloc->relent.sym_ptr_ptr = symbol_ptr_ptr;
+ reloc->next = rel_section->constructor_chain;
+ rel_section->constructor_chain = reloc;
+ reloc->relent.address = rel_section->_cooked_size;
+ /* ask the cpu which howto to use */
+ reloc->relent.howto = bfd_reloc_type_lookup(abfd, BFD_RELOC_CTOR);
+ rel_section->_cooked_size += sizeof(int *);
+ rel_section->reloc_count++;
+ }
+
+}
diff --git a/gnu/usr.bin/gdb/bfd/ecoff.c b/gnu/usr.bin/gdb/bfd/ecoff.c
new file mode 100644
index 000000000000..e3b7c937aa05
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/ecoff.c
@@ -0,0 +1,3994 @@
+/* Generic ECOFF (Extended-COFF) routines.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Original version by Per Bothner.
+ Full support added by Ian Lance Taylor, ian@cygnus.com.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "seclet.h"
+#include "aout/ar.h"
+#include "aout/ranlib.h"
+
+/* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines
+ some other stuff which we don't want and which conflicts with stuff
+ we do want. */
+#include "libaout.h"
+#include "aout/aout64.h"
+#undef N_ABS
+#undef exec_hdr
+#undef obj_sym_filepos
+
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "coff/symconst.h"
+#include "coff/ecoff.h"
+#include "libcoff.h"
+#include "libecoff.h"
+
+/* Prototypes for static functions. */
+
+static int ecoff_get_magic PARAMS ((bfd *abfd));
+static void ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
+ asymbol *asym, int ext,
+ asymbol **indirect_ptr_ptr));
+static void ecoff_emit_aggregate PARAMS ((bfd *abfd, char *string,
+ RNDXR *rndx, long isym,
+ CONST char *which));
+static char *ecoff_type_to_string PARAMS ((bfd *abfd, union aux_ext *aux_ptr,
+ unsigned int indx, int bigendian));
+static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section,
+ asymbol **symbols));
+static void ecoff_clear_output_flags PARAMS ((bfd *abfd));
+static boolean ecoff_rel PARAMS ((bfd *output_bfd, bfd_seclet_type *seclet,
+ asection *output_section, PTR data,
+ boolean relocateable));
+static boolean ecoff_dump_seclet PARAMS ((bfd *abfd, bfd_seclet_type *seclet,
+ asection *section, PTR data,
+ boolean relocateable));
+static long ecoff_add_string PARAMS ((bfd *output_bfd, FDR *fdr,
+ CONST char *string, boolean external));
+static boolean ecoff_get_debug PARAMS ((bfd *output_bfd,
+ bfd_seclet_type *seclet,
+ asection *section,
+ boolean relocateable));
+static void ecoff_compute_section_file_positions PARAMS ((bfd *abfd));
+static unsigned int ecoff_armap_hash PARAMS ((CONST char *s,
+ unsigned int *rehash,
+ unsigned int size,
+ unsigned int hlog));
+
+/* This stuff is somewhat copied from coffcode.h. */
+
+static asection bfd_debug_section = { "*DEBUG*" };
+
+/* Create an ECOFF object. */
+
+boolean
+ecoff_mkobject (abfd)
+ bfd *abfd;
+{
+ abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *)
+ bfd_zalloc (abfd, sizeof (ecoff_data_type)));
+ if (abfd->tdata.ecoff_obj_data == NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ /* Always create a .scommon section for every BFD. This is a hack so
+ that the linker has something to attach scSCommon symbols to. */
+ if (bfd_make_section (abfd, SCOMMON) == NULL)
+ return false;
+
+ return true;
+}
+
+/* This is a hook called by coff_real_object_p to create any backend
+ specific information. */
+
+PTR
+ecoff_mkobject_hook (abfd, filehdr, aouthdr)
+ bfd *abfd;
+ PTR filehdr;
+ PTR aouthdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+ struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
+ ecoff_data_type *ecoff;
+ asection *regsec;
+
+ if (ecoff_mkobject (abfd) == false)
+ return NULL;
+
+ ecoff = ecoff_data (abfd);
+ ecoff->gp_size = 8;
+ ecoff->sym_filepos = internal_f->f_symptr;
+
+ /* Create the .reginfo section to give programs outside BFD a way to
+ see the information stored in the a.out header. See the comment
+ in coff/ecoff.h. */
+ regsec = bfd_make_section (abfd, REGINFO);
+ if (regsec == NULL)
+ return NULL;
+
+ if (internal_a != (struct internal_aouthdr *) NULL)
+ {
+ int i;
+
+ ecoff->text_start = internal_a->text_start;
+ ecoff->text_end = internal_a->text_start + internal_a->tsize;
+ ecoff->gp = internal_a->gp_value;
+ ecoff->gprmask = internal_a->gprmask;
+ for (i = 0; i < 4; i++)
+ ecoff->cprmask[i] = internal_a->cprmask[i];
+ ecoff->fprmask = internal_a->fprmask;
+ if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
+ abfd->flags |= D_PAGED;
+ }
+
+ /* It turns out that no special action is required by the MIPS or
+ Alpha ECOFF backends. They have different information in the
+ a.out header, but we just copy it all (e.g., gprmask, cprmask and
+ fprmask) and let the swapping routines ensure that only relevant
+ information is written out. */
+
+ return (PTR) ecoff;
+}
+
+/* This is a hook needed by SCO COFF, but we have nothing to do. */
+
+asection *
+ecoff_make_section_hook (abfd, name)
+ bfd *abfd;
+ char *name;
+{
+ return (asection *) NULL;
+}
+
+/* Initialize a new section. */
+
+boolean
+ecoff_new_section_hook (abfd, section)
+ bfd *abfd;
+ asection *section;
+{
+ section->alignment_power = abfd->xvec->align_power_min;
+
+ if (strcmp (section->name, _TEXT) == 0)
+ section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
+ else if (strcmp (section->name, _DATA) == 0
+ || strcmp (section->name, _SDATA) == 0)
+ section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
+ else if (strcmp (section->name, _RDATA) == 0
+ || strcmp (section->name, _LIT8) == 0
+ || strcmp (section->name, _LIT4) == 0)
+ section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
+ else if (strcmp (section->name, _BSS) == 0
+ || strcmp (section->name, _SBSS) == 0)
+ section->flags |= SEC_ALLOC;
+ else if (strcmp (section->name, REGINFO) == 0)
+ {
+ section->flags |= SEC_HAS_CONTENTS | SEC_NEVER_LOAD;
+ section->_raw_size = sizeof (struct ecoff_reginfo);
+ }
+
+ /* Probably any other section name is SEC_NEVER_LOAD, but I'm
+ uncertain about .init on some systems and I don't know how shared
+ libraries work. */
+
+ return true;
+}
+
+/* Determine the machine architecture and type. This is called from
+ the generic COFF routines. It is the inverse of ecoff_get_magic,
+ below. This could be an ECOFF backend routine, with one version
+ for each target, but there aren't all that many ECOFF targets. */
+
+boolean
+ecoff_set_arch_mach_hook (abfd, filehdr)
+ bfd *abfd;
+ PTR filehdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+ enum bfd_architecture arch;
+ unsigned long mach;
+
+ switch (internal_f->f_magic)
+ {
+ case MIPS_MAGIC_1:
+ case MIPS_MAGIC_LITTLE:
+ case MIPS_MAGIC_BIG:
+ arch = bfd_arch_mips;
+ mach = 3000;
+ break;
+
+ case MIPS_MAGIC_LITTLE2:
+ case MIPS_MAGIC_BIG2:
+ /* MIPS ISA level 2: the r6000 */
+ arch = bfd_arch_mips;
+ mach = 6000;
+ break;
+
+ case MIPS_MAGIC_LITTLE3:
+ case MIPS_MAGIC_BIG3:
+ /* MIPS ISA level 3: the r4000 */
+ arch = bfd_arch_mips;
+ mach = 4000;
+ break;
+
+ case ALPHA_MAGIC:
+ arch = bfd_arch_alpha;
+ mach = 0;
+ break;
+
+ default:
+ arch = bfd_arch_obscure;
+ mach = 0;
+ break;
+ }
+
+ return bfd_default_set_arch_mach (abfd, arch, mach);
+}
+
+/* Get the magic number to use based on the architecture and machine.
+ This is the inverse of ecoff_set_arch_mach_hook, above. */
+
+static int
+ecoff_get_magic (abfd)
+ bfd *abfd;
+{
+ int big, little;
+
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_mips:
+ switch (bfd_get_mach (abfd))
+ {
+ default:
+ case 0:
+ case 3000:
+ big = MIPS_MAGIC_BIG;
+ little = MIPS_MAGIC_LITTLE;
+ break;
+
+ case 6000:
+ big = MIPS_MAGIC_BIG2;
+ little = MIPS_MAGIC_LITTLE2;
+ break;
+
+ case 4000:
+ big = MIPS_MAGIC_BIG3;
+ little = MIPS_MAGIC_LITTLE3;
+ break;
+ }
+
+ return abfd->xvec->byteorder_big_p ? big : little;
+
+ case bfd_arch_alpha:
+ return ALPHA_MAGIC;
+
+ default:
+ abort ();
+ return 0;
+ }
+}
+
+/* Get the section s_flags to use for a section. */
+
+long
+ecoff_sec_to_styp_flags (name, flags)
+ CONST char *name;
+ flagword flags;
+{
+ long styp;
+
+ styp = 0;
+
+ if (strcmp (name, _TEXT) == 0)
+ styp = STYP_TEXT;
+ else if (strcmp (name, _DATA) == 0)
+ styp = STYP_DATA;
+ else if (strcmp (name, _SDATA) == 0)
+ styp = STYP_SDATA;
+ else if (strcmp (name, _RDATA) == 0)
+ styp = STYP_RDATA;
+ else if (strcmp (name, _LIT8) == 0)
+ styp = STYP_LIT8;
+ else if (strcmp (name, _LIT4) == 0)
+ styp = STYP_LIT4;
+ else if (strcmp (name, _BSS) == 0)
+ styp = STYP_BSS;
+ else if (strcmp (name, _SBSS) == 0)
+ styp = STYP_SBSS;
+ else if (strcmp (name, _INIT) == 0)
+ styp = STYP_ECOFF_INIT;
+ else if (strcmp (name, _FINI) == 0)
+ styp = STYP_ECOFF_FINI;
+ else if (flags & SEC_CODE)
+ styp = STYP_TEXT;
+ else if (flags & SEC_DATA)
+ styp = STYP_DATA;
+ else if (flags & SEC_READONLY)
+ styp = STYP_RDATA;
+ else if (flags & SEC_LOAD)
+ styp = STYP_REG;
+ else
+ styp = STYP_BSS;
+
+ if (flags & SEC_NEVER_LOAD)
+ styp |= STYP_NOLOAD;
+
+ return styp;
+}
+
+/* Get the BFD flags to use for a section. */
+
+flagword
+ecoff_styp_to_sec_flags (abfd, hdr)
+ bfd *abfd;
+ PTR hdr;
+{
+ struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
+ long styp_flags = internal_s->s_flags;
+ flagword sec_flags=0;
+
+ if (styp_flags & STYP_NOLOAD)
+ sec_flags |= SEC_NEVER_LOAD;
+
+ /* For 386 COFF, at least, an unloadable text or data section is
+ actually a shared library section. */
+ if ((styp_flags & STYP_TEXT)
+ || (styp_flags & STYP_ECOFF_INIT)
+ || (styp_flags & STYP_ECOFF_FINI))
+ {
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY;
+ else
+ sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
+ }
+ else if ((styp_flags & STYP_DATA)
+ || (styp_flags & STYP_RDATA)
+ || (styp_flags & STYP_SDATA))
+ {
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_DATA | SEC_SHARED_LIBRARY;
+ else
+ sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
+ if (styp_flags & STYP_RDATA)
+ sec_flags |= SEC_READONLY;
+ }
+ else if ((styp_flags & STYP_BSS)
+ || (styp_flags & STYP_SBSS))
+ {
+ sec_flags |= SEC_ALLOC;
+ }
+ else if (styp_flags & STYP_INFO)
+ {
+ sec_flags |= SEC_NEVER_LOAD;
+ }
+ else if ((styp_flags & STYP_LIT8)
+ || (styp_flags & STYP_LIT4))
+ {
+ sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
+ }
+ else
+ {
+ sec_flags |= SEC_ALLOC | SEC_LOAD;
+ }
+
+ return sec_flags;
+}
+
+/* Routines to swap auxiliary information in and out. I am assuming
+ that the auxiliary information format is always going to be target
+ independent. */
+
+/* Swap in a type information record.
+ BIGEND says whether AUX symbols are big-endian or little-endian; this
+ info comes from the file header record (fh-fBigendian). */
+
+void
+ecoff_swap_tir_in (bigend, ext_copy, intern)
+ int bigend;
+ struct tir_ext *ext_copy;
+ TIR *intern;
+{
+ struct tir_ext ext[1];
+
+ *ext = *ext_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bigend) {
+ intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_BIG);
+ intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_BIG);
+ intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_BIG)
+ >> TIR_BITS1_BT_SH_BIG;
+ intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_BIG)
+ >> TIR_BITS_TQ4_SH_BIG;
+ intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_BIG)
+ >> TIR_BITS_TQ5_SH_BIG;
+ intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_BIG)
+ >> TIR_BITS_TQ0_SH_BIG;
+ intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_BIG)
+ >> TIR_BITS_TQ1_SH_BIG;
+ intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_BIG)
+ >> TIR_BITS_TQ2_SH_BIG;
+ intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_BIG)
+ >> TIR_BITS_TQ3_SH_BIG;
+ } else {
+ intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_LITTLE);
+ intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_LITTLE);
+ intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_LITTLE)
+ >> TIR_BITS1_BT_SH_LITTLE;
+ intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_LITTLE)
+ >> TIR_BITS_TQ4_SH_LITTLE;
+ intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_LITTLE)
+ >> TIR_BITS_TQ5_SH_LITTLE;
+ intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_LITTLE)
+ >> TIR_BITS_TQ0_SH_LITTLE;
+ intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_LITTLE)
+ >> TIR_BITS_TQ1_SH_LITTLE;
+ intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_LITTLE)
+ >> TIR_BITS_TQ2_SH_LITTLE;
+ intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_LITTLE)
+ >> TIR_BITS_TQ3_SH_LITTLE;
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out a type information record.
+ BIGEND says whether AUX symbols are big-endian or little-endian; this
+ info comes from the file header record (fh-fBigendian). */
+
+void
+ecoff_swap_tir_out (bigend, intern_copy, ext)
+ int bigend;
+ TIR *intern_copy;
+ struct tir_ext *ext;
+{
+ TIR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bigend) {
+ ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_BIG : 0)
+ | (intern->continued ? TIR_BITS1_CONTINUED_BIG : 0)
+ | ((intern->bt << TIR_BITS1_BT_SH_BIG)
+ & TIR_BITS1_BT_BIG));
+ ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_BIG)
+ & TIR_BITS_TQ4_BIG)
+ | ((intern->tq5 << TIR_BITS_TQ5_SH_BIG)
+ & TIR_BITS_TQ5_BIG));
+ ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_BIG)
+ & TIR_BITS_TQ0_BIG)
+ | ((intern->tq1 << TIR_BITS_TQ1_SH_BIG)
+ & TIR_BITS_TQ1_BIG));
+ ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_BIG)
+ & TIR_BITS_TQ2_BIG)
+ | ((intern->tq3 << TIR_BITS_TQ3_SH_BIG)
+ & TIR_BITS_TQ3_BIG));
+ } else {
+ ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_LITTLE : 0)
+ | (intern->continued ? TIR_BITS1_CONTINUED_LITTLE : 0)
+ | ((intern->bt << TIR_BITS1_BT_SH_LITTLE)
+ & TIR_BITS1_BT_LITTLE));
+ ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_LITTLE)
+ & TIR_BITS_TQ4_LITTLE)
+ | ((intern->tq5 << TIR_BITS_TQ5_SH_LITTLE)
+ & TIR_BITS_TQ5_LITTLE));
+ ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_LITTLE)
+ & TIR_BITS_TQ0_LITTLE)
+ | ((intern->tq1 << TIR_BITS_TQ1_SH_LITTLE)
+ & TIR_BITS_TQ1_LITTLE));
+ ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_LITTLE)
+ & TIR_BITS_TQ2_LITTLE)
+ | ((intern->tq3 << TIR_BITS_TQ3_SH_LITTLE)
+ & TIR_BITS_TQ3_LITTLE));
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap in a relative symbol record. BIGEND says whether it is in
+ big-endian or little-endian format.*/
+
+void
+ecoff_swap_rndx_in (bigend, ext_copy, intern)
+ int bigend;
+ struct rndx_ext *ext_copy;
+ RNDXR *intern;
+{
+ struct rndx_ext ext[1];
+
+ *ext = *ext_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bigend) {
+ intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_BIG)
+ | ((ext->r_bits[1] & RNDX_BITS1_RFD_BIG)
+ >> RNDX_BITS1_RFD_SH_BIG);
+ intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_BIG)
+ << RNDX_BITS1_INDEX_SH_LEFT_BIG)
+ | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_BIG)
+ | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_BIG);
+ } else {
+ intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_LITTLE)
+ | ((ext->r_bits[1] & RNDX_BITS1_RFD_LITTLE)
+ << RNDX_BITS1_RFD_SH_LEFT_LITTLE);
+ intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE)
+ >> RNDX_BITS1_INDEX_SH_LITTLE)
+ | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE)
+ | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_LITTLE);
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out a relative symbol record. BIGEND says whether it is in
+ big-endian or little-endian format.*/
+
+void
+ecoff_swap_rndx_out (bigend, intern_copy, ext)
+ int bigend;
+ RNDXR *intern_copy;
+ struct rndx_ext *ext;
+{
+ RNDXR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bigend) {
+ ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_BIG;
+ ext->r_bits[1] = (((intern->rfd << RNDX_BITS1_RFD_SH_BIG)
+ & RNDX_BITS1_RFD_BIG)
+ | ((intern->index >> RNDX_BITS1_INDEX_SH_LEFT_BIG)
+ & RNDX_BITS1_INDEX_BIG));
+ ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_BIG;
+ ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_BIG;
+ } else {
+ ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_LITTLE;
+ ext->r_bits[1] = (((intern->rfd >> RNDX_BITS1_RFD_SH_LEFT_LITTLE)
+ & RNDX_BITS1_RFD_LITTLE)
+ | ((intern->index << RNDX_BITS1_INDEX_SH_LITTLE)
+ & RNDX_BITS1_INDEX_LITTLE));
+ ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_LITTLE;
+ ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_LITTLE;
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Read in and swap the important symbolic information for an ECOFF
+ object file. This is called by gdb. */
+
+boolean
+ecoff_slurp_symbolic_info (abfd)
+ bfd *abfd;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ bfd_size_type external_hdr_size;
+ HDRR *internal_symhdr;
+ bfd_size_type raw_base;
+ bfd_size_type raw_size;
+ PTR raw;
+ bfd_size_type external_fdr_size;
+ char *fraw_src;
+ char *fraw_end;
+ struct fdr *fdr_ptr;
+ bfd_size_type raw_end;
+ bfd_size_type cb_end;
+
+ /* Check whether we've already gotten it, and whether there's any to
+ get. */
+ if (ecoff_data (abfd)->raw_syments != (PTR) NULL)
+ return true;
+ if (ecoff_data (abfd)->sym_filepos == 0)
+ {
+ bfd_get_symcount (abfd) = 0;
+ return true;
+ }
+
+ /* At this point bfd_get_symcount (abfd) holds the number of symbols
+ as read from the file header, but on ECOFF this is always the
+ size of the symbolic information header. It would be cleaner to
+ handle this when we first read the file in coffgen.c. */
+ external_hdr_size = backend->external_hdr_size;
+ if (bfd_get_symcount (abfd) != external_hdr_size)
+ {
+ bfd_error = bad_value;
+ return false;
+ }
+
+ /* Read the symbolic information header. */
+ raw = (PTR) alloca (external_hdr_size);
+ if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1
+ || (bfd_read (raw, external_hdr_size, 1, abfd)
+ != external_hdr_size))
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+ internal_symhdr = &ecoff_data (abfd)->symbolic_header;
+ (*backend->swap_hdr_in) (abfd, raw, internal_symhdr);
+
+ if (internal_symhdr->magic != backend->sym_magic)
+ {
+ bfd_error = bad_value;
+ return false;
+ }
+
+ /* Now we can get the correct number of symbols. */
+ bfd_get_symcount (abfd) = (internal_symhdr->isymMax
+ + internal_symhdr->iextMax);
+
+ /* Read all the symbolic information at once. */
+ raw_base = ecoff_data (abfd)->sym_filepos + external_hdr_size;
+
+ /* Alpha ecoff makes the determination of raw_size difficult. It has
+ an undocumented debug data section between the symhdr and the first
+ documented section. And the ordering of the sections varies between
+ statically and dynamically linked executables.
+ If bfd supports SEEK_END someday, this code could be simplified. */
+
+ raw_end = 0;
+
+#define UPDATE_RAW_END(start, count, size) \
+ cb_end = internal_symhdr->start + internal_symhdr->count * (size); \
+ if (cb_end > raw_end) \
+ raw_end = cb_end
+
+ UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char));
+ UPDATE_RAW_END (cbDnOffset, idnMax, backend->external_dnr_size);
+ UPDATE_RAW_END (cbPdOffset, ipdMax, backend->external_pdr_size);
+ UPDATE_RAW_END (cbSymOffset, isymMax, backend->external_sym_size);
+ UPDATE_RAW_END (cbOptOffset, ioptMax, backend->external_opt_size);
+ UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext));
+ UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char));
+ UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char));
+ UPDATE_RAW_END (cbFdOffset, ifdMax, backend->external_fdr_size);
+ UPDATE_RAW_END (cbRfdOffset, crfd, backend->external_rfd_size);
+ UPDATE_RAW_END (cbExtOffset, iextMax, backend->external_ext_size);
+
+#undef UPDATE_RAW_END
+
+ raw_size = raw_end - raw_base;
+ if (raw_size == 0)
+ {
+ ecoff_data (abfd)->sym_filepos = 0;
+ return true;
+ }
+ raw = (PTR) bfd_alloc (abfd, raw_size);
+ if (raw == NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ if (bfd_read (raw, raw_size, 1, abfd) != raw_size)
+ {
+ bfd_error = system_call_error;
+ bfd_release (abfd, raw);
+ return false;
+ }
+
+ ecoff_data (abfd)->raw_size = raw_size;
+ ecoff_data (abfd)->raw_syments = raw;
+
+ /* Get pointers for the numeric offsets in the HDRR structure. */
+#define FIX(off1, off2, type) \
+ if (internal_symhdr->off1 == 0) \
+ ecoff_data (abfd)->off2 = (type) NULL; \
+ else \
+ ecoff_data (abfd)->off2 = (type) ((char *) raw \
+ + internal_symhdr->off1 \
+ - raw_base)
+ FIX (cbLineOffset, line, unsigned char *);
+ FIX (cbDnOffset, external_dnr, PTR);
+ FIX (cbPdOffset, external_pdr, PTR);
+ FIX (cbSymOffset, external_sym, PTR);
+ FIX (cbOptOffset, external_opt, PTR);
+ FIX (cbAuxOffset, external_aux, union aux_ext *);
+ FIX (cbSsOffset, ss, char *);
+ FIX (cbSsExtOffset, ssext, char *);
+ FIX (cbFdOffset, external_fdr, PTR);
+ FIX (cbRfdOffset, external_rfd, PTR);
+ FIX (cbExtOffset, external_ext, PTR);
+#undef FIX
+
+ /* I don't want to always swap all the data, because it will just
+ waste time and most programs will never look at it. The only
+ time the linker needs most of the debugging information swapped
+ is when linking big-endian and little-endian MIPS object files
+ together, which is not a common occurrence.
+
+ We need to look at the fdr to deal with a lot of information in
+ the symbols, so we swap them here. */
+ ecoff_data (abfd)->fdr =
+ (struct fdr *) bfd_alloc (abfd,
+ (internal_symhdr->ifdMax *
+ sizeof (struct fdr)));
+ if (ecoff_data (abfd)->fdr == NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ external_fdr_size = backend->external_fdr_size;
+ fdr_ptr = ecoff_data (abfd)->fdr;
+ fraw_src = (char *) ecoff_data (abfd)->external_fdr;
+ fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size;
+ for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
+ (*backend->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
+
+ return true;
+}
+
+/* ECOFF symbol table routines. The ECOFF symbol table is described
+ in gcc/mips-tfile.c. */
+
+/* ECOFF uses two common sections. One is the usual one, and the
+ other is for small objects. All the small objects are kept
+ together, and then referenced via the gp pointer, which yields
+ faster assembler code. This is what we use for the small common
+ section. */
+static asection ecoff_scom_section;
+static asymbol ecoff_scom_symbol;
+static asymbol *ecoff_scom_symbol_ptr;
+
+/* Create an empty symbol. */
+
+asymbol *
+ecoff_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ ecoff_symbol_type *new;
+
+ new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type));
+ if (new == (ecoff_symbol_type *) NULL)
+ {
+ bfd_error = no_memory;
+ return (asymbol *) NULL;
+ }
+ memset (new, 0, sizeof *new);
+ new->symbol.section = (asection *) NULL;
+ new->fdr = (FDR *) NULL;
+ new->local = false;
+ new->native = NULL;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+/* Set the BFD flags and section for an ECOFF symbol. */
+
+static void
+ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
+ bfd *abfd;
+ SYMR *ecoff_sym;
+ asymbol *asym;
+ int ext;
+ asymbol **indirect_ptr_ptr;
+{
+ asym->the_bfd = abfd;
+ asym->value = ecoff_sym->value;
+ asym->section = &bfd_debug_section;
+ asym->udata = NULL;
+
+ /* An indirect symbol requires two consecutive stabs symbols. */
+ if (*indirect_ptr_ptr != (asymbol *) NULL)
+ {
+ BFD_ASSERT (ECOFF_IS_STAB (ecoff_sym));
+
+ /* @@ Stuffing pointers into integers is a no-no.
+ We can usually get away with it if the integer is
+ large enough though. */
+ if (sizeof (asym) > sizeof (bfd_vma))
+ abort ();
+ (*indirect_ptr_ptr)->value = (bfd_vma) asym;
+
+ asym->flags = BSF_DEBUGGING;
+ asym->section = &bfd_und_section;
+ *indirect_ptr_ptr = NULL;
+ return;
+ }
+
+ if (ECOFF_IS_STAB (ecoff_sym)
+ && (ECOFF_UNMARK_STAB (ecoff_sym->index) | N_EXT) == (N_INDR | N_EXT))
+ {
+ asym->flags = BSF_DEBUGGING | BSF_INDIRECT;
+ asym->section = &bfd_ind_section;
+ /* Pass this symbol on to the next call to this function. */
+ *indirect_ptr_ptr = asym;
+ return;
+ }
+
+ /* Most symbol types are just for debugging. */
+ switch (ecoff_sym->st)
+ {
+ case stGlobal:
+ case stStatic:
+ case stLabel:
+ case stProc:
+ case stStaticProc:
+ break;
+ case stNil:
+ if (ECOFF_IS_STAB (ecoff_sym))
+ {
+ asym->flags = BSF_DEBUGGING;
+ return;
+ }
+ break;
+ default:
+ asym->flags = BSF_DEBUGGING;
+ return;
+ }
+
+ if (ext)
+ asym->flags = BSF_EXPORT | BSF_GLOBAL;
+ else
+ asym->flags = BSF_LOCAL;
+ switch (ecoff_sym->sc)
+ {
+ case scNil:
+ /* Used for compiler generated labels. Leave them in the
+ debugging section, and mark them as local. If BSF_DEBUGGING
+ is set, then nm does not display them for some reason. If no
+ flags are set then the linker whines about them. */
+ asym->flags = BSF_LOCAL;
+ break;
+ case scText:
+ asym->section = bfd_make_section_old_way (abfd, ".text");
+ asym->value -= asym->section->vma;
+ break;
+ case scData:
+ asym->section = bfd_make_section_old_way (abfd, ".data");
+ asym->value -= asym->section->vma;
+ break;
+ case scBss:
+ asym->section = bfd_make_section_old_way (abfd, ".bss");
+ asym->value -= asym->section->vma;
+ break;
+ case scRegister:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scAbs:
+ asym->section = &bfd_abs_section;
+ break;
+ case scUndefined:
+ asym->section = &bfd_und_section;
+ asym->flags = 0;
+ asym->value = 0;
+ break;
+ case scCdbLocal:
+ case scBits:
+ case scCdbSystem:
+ case scRegImage:
+ case scInfo:
+ case scUserStruct:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scSData:
+ asym->section = bfd_make_section_old_way (abfd, ".sdata");
+ asym->value -= asym->section->vma;
+ break;
+ case scSBss:
+ asym->section = bfd_make_section_old_way (abfd, ".sbss");
+ asym->value -= asym->section->vma;
+ break;
+ case scRData:
+ asym->section = bfd_make_section_old_way (abfd, ".rdata");
+ asym->value -= asym->section->vma;
+ break;
+ case scVar:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scCommon:
+ if (asym->value > ecoff_data (abfd)->gp_size)
+ {
+ asym->section = &bfd_com_section;
+ asym->flags = 0;
+ break;
+ }
+ /* Fall through. */
+ case scSCommon:
+ if (ecoff_scom_section.name == NULL)
+ {
+ /* Initialize the small common section. */
+ ecoff_scom_section.name = SCOMMON;
+ ecoff_scom_section.flags = SEC_IS_COMMON;
+ ecoff_scom_section.output_section = &ecoff_scom_section;
+ ecoff_scom_section.symbol = &ecoff_scom_symbol;
+ ecoff_scom_section.symbol_ptr_ptr = &ecoff_scom_symbol_ptr;
+ ecoff_scom_symbol.name = SCOMMON;
+ ecoff_scom_symbol.flags = BSF_SECTION_SYM;
+ ecoff_scom_symbol.section = &ecoff_scom_section;
+ ecoff_scom_symbol_ptr = &ecoff_scom_symbol;
+ }
+ asym->section = &ecoff_scom_section;
+ asym->flags = 0;
+ break;
+ case scVarRegister:
+ case scVariant:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scSUndefined:
+ asym->section = &bfd_und_section;
+ asym->flags = 0;
+ asym->value = 0;
+ break;
+ case scInit:
+ asym->section = bfd_make_section_old_way (abfd, ".init");
+ asym->value -= asym->section->vma;
+ break;
+ case scBasedVar:
+ case scXData:
+ case scPData:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scFini:
+ asym->section = bfd_make_section_old_way (abfd, ".fini");
+ asym->value -= asym->section->vma;
+ break;
+ default:
+ break;
+ }
+
+ /* Look for special constructors symbols and make relocation entries
+ in a special construction section. These are produced by the
+ -fgnu-linker argument to g++. */
+ if (ECOFF_IS_STAB (ecoff_sym))
+ {
+ switch (ECOFF_UNMARK_STAB (ecoff_sym->index))
+ {
+ default:
+ break;
+
+ case N_SETA:
+ case N_SETT:
+ case N_SETD:
+ case N_SETB:
+ {
+ const char *name;
+ asection *section;
+ arelent_chain *reloc_chain;
+ unsigned int bitsize;
+
+ /* Get a section with the same name as the symbol (usually
+ __CTOR_LIST__ or __DTOR_LIST__). FIXME: gcc uses the
+ name ___CTOR_LIST (three underscores). We need
+ __CTOR_LIST (two underscores), since ECOFF doesn't use
+ a leading underscore. This should be handled by gcc,
+ but instead we do it here. Actually, this should all
+ be done differently anyhow. */
+ name = bfd_asymbol_name (asym);
+ if (name[0] == '_' && name[1] == '_' && name[2] == '_')
+ {
+ ++name;
+ asym->name = name;
+ }
+ section = bfd_get_section_by_name (abfd, name);
+ if (section == (asection *) NULL)
+ {
+ char *copy;
+
+ copy = (char *) bfd_alloc (abfd, strlen (name) + 1);
+ strcpy (copy, name);
+ section = bfd_make_section (abfd, copy);
+ }
+
+ /* Build a reloc pointing to this constructor. */
+ reloc_chain =
+ (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
+ reloc_chain->relent.sym_ptr_ptr =
+ bfd_get_section (asym)->symbol_ptr_ptr;
+ reloc_chain->relent.address = section->_raw_size;
+ reloc_chain->relent.addend = asym->value;
+ reloc_chain->relent.howto =
+ ecoff_backend (abfd)->constructor_reloc;
+
+ /* Set up the constructor section to hold the reloc. */
+ section->flags = SEC_CONSTRUCTOR;
+ ++section->reloc_count;
+
+ /* Constructor sections must be rounded to a boundary
+ based on the bitsize. These are not real sections--
+ they are handled specially by the linker--so the ECOFF
+ 16 byte alignment restriction does not apply. */
+ bitsize = ecoff_backend (abfd)->constructor_bitsize;
+ section->alignment_power = 1;
+ while ((1 << section->alignment_power) < bitsize / 8)
+ ++section->alignment_power;
+
+ reloc_chain->next = section->constructor_chain;
+ section->constructor_chain = reloc_chain;
+ section->_raw_size += bitsize / 8;
+
+ /* Mark the symbol as a constructor. */
+ asym->flags |= BSF_CONSTRUCTOR;
+ }
+ break;
+ }
+ }
+}
+
+/* Read an ECOFF symbol table. */
+
+boolean
+ecoff_slurp_symbol_table (abfd)
+ bfd *abfd;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ const bfd_size_type external_ext_size = backend->external_ext_size;
+ const bfd_size_type external_sym_size = backend->external_sym_size;
+ void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *))
+ = backend->swap_ext_in;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = backend->swap_sym_in;
+ bfd_size_type internal_size;
+ ecoff_symbol_type *internal;
+ ecoff_symbol_type *internal_ptr;
+ asymbol *indirect_ptr;
+ char *eraw_src;
+ char *eraw_end;
+ FDR *fdr_ptr;
+ FDR *fdr_end;
+
+ /* If we've already read in the symbol table, do nothing. */
+ if (ecoff_data (abfd)->canonical_symbols != NULL)
+ return true;
+
+ /* Get the symbolic information. */
+ if (ecoff_slurp_symbolic_info (abfd) == false)
+ return false;
+ if (bfd_get_symcount (abfd) == 0)
+ return true;
+
+ internal_size = bfd_get_symcount (abfd) * sizeof (ecoff_symbol_type);
+ internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size);
+ if (internal == NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ internal_ptr = internal;
+ indirect_ptr = NULL;
+ eraw_src = (char *) ecoff_data (abfd)->external_ext;
+ eraw_end = (eraw_src
+ + (ecoff_data (abfd)->symbolic_header.iextMax
+ * external_ext_size));
+ for (; eraw_src < eraw_end; eraw_src += external_ext_size, internal_ptr++)
+ {
+ EXTR internal_esym;
+
+ (*swap_ext_in) (abfd, (PTR) eraw_src, &internal_esym);
+ internal_ptr->symbol.name = (ecoff_data (abfd)->ssext
+ + internal_esym.asym.iss);
+ ecoff_set_symbol_info (abfd, &internal_esym.asym,
+ &internal_ptr->symbol, 1, &indirect_ptr);
+ /* The alpha uses a negative ifd field for section symbols. */
+ if (internal_esym.ifd >= 0)
+ internal_ptr->fdr = ecoff_data (abfd)->fdr + internal_esym.ifd;
+ else
+ internal_ptr->fdr = NULL;
+ internal_ptr->local = false;
+ internal_ptr->native = (PTR) eraw_src;
+ }
+ BFD_ASSERT (indirect_ptr == (asymbol *) NULL);
+
+ /* The local symbols must be accessed via the fdr's, because the
+ string and aux indices are relative to the fdr information. */
+ fdr_ptr = ecoff_data (abfd)->fdr;
+ fdr_end = fdr_ptr + ecoff_data (abfd)->symbolic_header.ifdMax;
+ for (; fdr_ptr < fdr_end; fdr_ptr++)
+ {
+ char *lraw_src;
+ char *lraw_end;
+
+ lraw_src = ((char *) ecoff_data (abfd)->external_sym
+ + fdr_ptr->isymBase * external_sym_size);
+ lraw_end = lraw_src + fdr_ptr->csym * external_sym_size;
+ for (;
+ lraw_src < lraw_end;
+ lraw_src += external_sym_size, internal_ptr++)
+ {
+ SYMR internal_sym;
+
+ (*swap_sym_in) (abfd, (PTR) lraw_src, &internal_sym);
+ internal_ptr->symbol.name = (ecoff_data (abfd)->ss
+ + fdr_ptr->issBase
+ + internal_sym.iss);
+ ecoff_set_symbol_info (abfd, &internal_sym,
+ &internal_ptr->symbol, 0, &indirect_ptr);
+ internal_ptr->fdr = fdr_ptr;
+ internal_ptr->local = true;
+ internal_ptr->native = (PTR) lraw_src;
+ }
+ }
+ BFD_ASSERT (indirect_ptr == (asymbol *) NULL);
+
+ ecoff_data (abfd)->canonical_symbols = internal;
+
+ return true;
+}
+
+/* Return the amount of space needed for the canonical symbols. */
+
+unsigned int
+ecoff_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ if (ecoff_slurp_symbolic_info (abfd) == false
+ || bfd_get_symcount (abfd) == 0)
+ return 0;
+
+ return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *));
+}
+
+/* Get the canonicals symbols. */
+
+unsigned int
+ecoff_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ unsigned int counter = 0;
+ ecoff_symbol_type *symbase;
+ ecoff_symbol_type **location = (ecoff_symbol_type **) alocation;
+
+ if (ecoff_slurp_symbol_table (abfd) == false
+ || bfd_get_symcount (abfd) == 0)
+ return 0;
+
+ symbase = ecoff_data (abfd)->canonical_symbols;
+ while (counter < bfd_get_symcount (abfd))
+ {
+ *(location++) = symbase++;
+ counter++;
+ }
+ *location++ = (ecoff_symbol_type *) NULL;
+ return bfd_get_symcount (abfd);
+}
+
+/* Turn ECOFF type information into a printable string.
+ ecoff_emit_aggregate and ecoff_type_to_string are from
+ gcc/mips-tdump.c, with swapping added and used_ptr removed. */
+
+/* Write aggregate information to a string. */
+
+static void
+ecoff_emit_aggregate (abfd, string, rndx, isym, which)
+ bfd *abfd;
+ char *string;
+ RNDXR *rndx;
+ long isym;
+ CONST char *which;
+{
+ int ifd = rndx->rfd;
+ int indx = rndx->index;
+ int sym_base, ss_base;
+ CONST char *name;
+
+ if (ifd == 0xfff)
+ ifd = isym;
+
+ sym_base = ecoff_data (abfd)->fdr[ifd].isymBase;
+ ss_base = ecoff_data (abfd)->fdr[ifd].issBase;
+
+ if (indx == indexNil)
+ name = "/* no name */";
+ else
+ {
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ SYMR sym;
+
+ indx += sym_base;
+ (*backend->swap_sym_in) (abfd,
+ ((char *) ecoff_data (abfd)->external_sym
+ + indx * backend->external_sym_size),
+ &sym);
+ name = ecoff_data (abfd)->ss + ss_base + sym.iss;
+ }
+
+ sprintf (string,
+ "%s %s { ifd = %d, index = %d }",
+ which, name, ifd,
+ indx + ecoff_data (abfd)->symbolic_header.iextMax);
+}
+
+/* Convert the type information to string format. */
+
+static char *
+ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
+ bfd *abfd;
+ union aux_ext *aux_ptr;
+ unsigned int indx;
+ int bigendian;
+{
+ AUXU u;
+ struct qual {
+ unsigned int type;
+ int low_bound;
+ int high_bound;
+ int stride;
+ } qualifiers[7];
+
+ unsigned int basic_type;
+ int i;
+ static char buffer1[1024];
+ static char buffer2[1024];
+ char *p1 = buffer1;
+ char *p2 = buffer2;
+ RNDXR rndx;
+
+ for (i = 0; i < 7; i++)
+ {
+ qualifiers[i].low_bound = 0;
+ qualifiers[i].high_bound = 0;
+ qualifiers[i].stride = 0;
+ }
+
+ if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == -1)
+ return "-1 (no type)";
+ ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti);
+
+ basic_type = u.ti.bt;
+ qualifiers[0].type = u.ti.tq0;
+ qualifiers[1].type = u.ti.tq1;
+ qualifiers[2].type = u.ti.tq2;
+ qualifiers[3].type = u.ti.tq3;
+ qualifiers[4].type = u.ti.tq4;
+ qualifiers[5].type = u.ti.tq5;
+ qualifiers[6].type = tqNil;
+
+ /*
+ * Go get the basic type.
+ */
+ switch (basic_type)
+ {
+ case btNil: /* undefined */
+ strcpy (p1, "nil");
+ break;
+
+ case btAdr: /* address - integer same size as pointer */
+ strcpy (p1, "address");
+ break;
+
+ case btChar: /* character */
+ strcpy (p1, "char");
+ break;
+
+ case btUChar: /* unsigned character */
+ strcpy (p1, "unsigned char");
+ break;
+
+ case btShort: /* short */
+ strcpy (p1, "short");
+ break;
+
+ case btUShort: /* unsigned short */
+ strcpy (p1, "unsigned short");
+ break;
+
+ case btInt: /* int */
+ strcpy (p1, "int");
+ break;
+
+ case btUInt: /* unsigned int */
+ strcpy (p1, "unsigned int");
+ break;
+
+ case btLong: /* long */
+ strcpy (p1, "long");
+ break;
+
+ case btULong: /* unsigned long */
+ strcpy (p1, "unsigned long");
+ break;
+
+ case btFloat: /* float (real) */
+ strcpy (p1, "float");
+ break;
+
+ case btDouble: /* Double (real) */
+ strcpy (p1, "double");
+ break;
+
+ /* Structures add 1-2 aux words:
+ 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
+ 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+
+ case btStruct: /* Structure (Record) */
+ ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+ ecoff_emit_aggregate (abfd, p1, &rndx,
+ AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
+ "struct");
+ indx++; /* skip aux words */
+ break;
+
+ /* Unions add 1-2 aux words:
+ 1st word is [ST_RFDESCAPE, offset] pointer to union def;
+ 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+
+ case btUnion: /* Union */
+ ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+ ecoff_emit_aggregate (abfd, p1, &rndx,
+ AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
+ "union");
+ indx++; /* skip aux words */
+ break;
+
+ /* Enumerations add 1-2 aux words:
+ 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
+ 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+
+ case btEnum: /* Enumeration */
+ ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+ ecoff_emit_aggregate (abfd, p1, &rndx,
+ AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
+ "enum");
+ indx++; /* skip aux words */
+ break;
+
+ case btTypedef: /* defined via a typedef, isymRef points */
+ strcpy (p1, "typedef");
+ break;
+
+ case btRange: /* subrange of int */
+ strcpy (p1, "subrange");
+ break;
+
+ case btSet: /* pascal sets */
+ strcpy (p1, "set");
+ break;
+
+ case btComplex: /* fortran complex */
+ strcpy (p1, "complex");
+ break;
+
+ case btDComplex: /* fortran double complex */
+ strcpy (p1, "double complex");
+ break;
+
+ case btIndirect: /* forward or unnamed typedef */
+ strcpy (p1, "forward/unamed typedef");
+ break;
+
+ case btFixedDec: /* Fixed Decimal */
+ strcpy (p1, "fixed decimal");
+ break;
+
+ case btFloatDec: /* Float Decimal */
+ strcpy (p1, "float decimal");
+ break;
+
+ case btString: /* Varying Length Character String */
+ strcpy (p1, "string");
+ break;
+
+ case btBit: /* Aligned Bit String */
+ strcpy (p1, "bit");
+ break;
+
+ case btPicture: /* Picture */
+ strcpy (p1, "picture");
+ break;
+
+ case btVoid: /* Void */
+ strcpy (p1, "void");
+ break;
+
+ default:
+ sprintf (p1, "Unknown basic type %d", (int) basic_type);
+ break;
+ }
+
+ p1 += strlen (buffer1);
+
+ /*
+ * If this is a bitfield, get the bitsize.
+ */
+ if (u.ti.fBitfield)
+ {
+ int bitsize;
+
+ bitsize = AUX_GET_WIDTH (bigendian, &aux_ptr[indx++]);
+ sprintf (p1, " : %d", bitsize);
+ p1 += strlen (buffer1);
+ }
+
+
+ /*
+ * Deal with any qualifiers.
+ */
+ if (qualifiers[0].type != tqNil)
+ {
+ /*
+ * Snarf up any array bounds in the correct order. Arrays
+ * store 5 successive words in the aux. table:
+ * word 0 RNDXR to type of the bounds (ie, int)
+ * word 1 Current file descriptor index
+ * word 2 low bound
+ * word 3 high bound (or -1 if [])
+ * word 4 stride size in bits
+ */
+ for (i = 0; i < 7; i++)
+ {
+ if (qualifiers[i].type == tqArray)
+ {
+ qualifiers[i].low_bound =
+ AUX_GET_DNLOW (bigendian, &aux_ptr[indx+2]);
+ qualifiers[i].high_bound =
+ AUX_GET_DNHIGH (bigendian, &aux_ptr[indx+3]);
+ qualifiers[i].stride =
+ AUX_GET_WIDTH (bigendian, &aux_ptr[indx+4]);
+ indx += 5;
+ }
+ }
+
+ /*
+ * Now print out the qualifiers.
+ */
+ for (i = 0; i < 6; i++)
+ {
+ switch (qualifiers[i].type)
+ {
+ case tqNil:
+ case tqMax:
+ break;
+
+ case tqPtr:
+ strcpy (p2, "ptr to ");
+ p2 += sizeof ("ptr to ")-1;
+ break;
+
+ case tqVol:
+ strcpy (p2, "volatile ");
+ p2 += sizeof ("volatile ")-1;
+ break;
+
+ case tqFar:
+ strcpy (p2, "far ");
+ p2 += sizeof ("far ")-1;
+ break;
+
+ case tqProc:
+ strcpy (p2, "func. ret. ");
+ p2 += sizeof ("func. ret. ");
+ break;
+
+ case tqArray:
+ {
+ int first_array = i;
+ int j;
+
+ /* Print array bounds reversed (ie, in the order the C
+ programmer writes them). C is such a fun language.... */
+
+ while (i < 5 && qualifiers[i+1].type == tqArray)
+ i++;
+
+ for (j = i; j >= first_array; j--)
+ {
+ strcpy (p2, "array [");
+ p2 += sizeof ("array [")-1;
+ if (qualifiers[j].low_bound != 0)
+ sprintf (p2,
+ "%ld:%ld {%ld bits}",
+ (long) qualifiers[j].low_bound,
+ (long) qualifiers[j].high_bound,
+ (long) qualifiers[j].stride);
+
+ else if (qualifiers[j].high_bound != -1)
+ sprintf (p2,
+ "%ld {%ld bits}",
+ (long) (qualifiers[j].high_bound + 1),
+ (long) (qualifiers[j].stride));
+
+ else
+ sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
+
+ p2 += strlen (p2);
+ strcpy (p2, "] of ");
+ p2 += sizeof ("] of ")-1;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ strcpy (p2, buffer1);
+ return buffer2;
+}
+
+/* Return information about ECOFF symbol SYMBOL in RET. */
+
+void
+ecoff_get_symbol_info (abfd, symbol, ret)
+ bfd *abfd; /* Ignored. */
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+/* Print information about an ECOFF symbol. */
+
+void
+ecoff_print_symbol (abfd, filep, symbol, how)
+ bfd *abfd;
+ PTR filep;
+ asymbol *symbol;
+ bfd_print_symbol_type how;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ FILE *file = (FILE *)filep;
+
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ fprintf (file, "%s", symbol->name);
+ break;
+ case bfd_print_symbol_more:
+ if (ecoffsymbol (symbol)->local)
+ {
+ SYMR ecoff_sym;
+
+ (*backend->swap_sym_in) (abfd, ecoffsymbol (symbol)->native,
+ &ecoff_sym);
+ fprintf (file, "ecoff local ");
+ fprintf_vma (file, (bfd_vma) ecoff_sym.value);
+ fprintf (file, " %x %x", (unsigned) ecoff_sym.st,
+ (unsigned) ecoff_sym.sc);
+ }
+ else
+ {
+ EXTR ecoff_ext;
+
+ (*backend->swap_ext_in) (abfd, ecoffsymbol (symbol)->native,
+ &ecoff_ext);
+ fprintf (file, "ecoff extern ");
+ fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value);
+ fprintf (file, " %x %x", (unsigned) ecoff_ext.asym.st,
+ (unsigned) ecoff_ext.asym.sc);
+ }
+ break;
+ case bfd_print_symbol_all:
+ /* Print out the symbols in a reasonable way */
+ {
+ char type;
+ int pos;
+ EXTR ecoff_ext;
+ char jmptbl;
+ char cobol_main;
+ char weakext;
+
+ if (ecoffsymbol (symbol)->local)
+ {
+ (*backend->swap_sym_in) (abfd, ecoffsymbol (symbol)->native,
+ &ecoff_ext.asym);
+ type = 'l';
+ pos = ((((char *) ecoffsymbol (symbol)->native
+ - (char *) ecoff_data (abfd)->external_sym)
+ / backend->external_sym_size)
+ + ecoff_data (abfd)->symbolic_header.iextMax);
+ jmptbl = ' ';
+ cobol_main = ' ';
+ weakext = ' ';
+ }
+ else
+ {
+ (*backend->swap_ext_in) (abfd, ecoffsymbol (symbol)->native,
+ &ecoff_ext);
+ type = 'e';
+ pos = (((char *) ecoffsymbol (symbol)->native
+ - (char *) ecoff_data (abfd)->external_ext)
+ / backend->external_ext_size);
+ jmptbl = ecoff_ext.jmptbl ? 'j' : ' ';
+ cobol_main = ecoff_ext.cobol_main ? 'c' : ' ';
+ weakext = ecoff_ext.weakext ? 'w' : ' ';
+ }
+
+ fprintf (file, "[%3d] %c ",
+ pos, type);
+ fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value);
+ fprintf (file, " st %x sc %x indx %x %c%c%c %s",
+ (unsigned) ecoff_ext.asym.st,
+ (unsigned) ecoff_ext.asym.sc,
+ (unsigned) ecoff_ext.asym.index,
+ jmptbl, cobol_main, weakext,
+ symbol->name);
+
+ if (ecoffsymbol (symbol)->fdr != NULL
+ && ecoff_ext.asym.index != indexNil)
+ {
+ unsigned int indx;
+ int bigendian;
+ bfd_size_type sym_base;
+ union aux_ext *aux_base;
+
+ indx = ecoff_ext.asym.index;
+
+ /* sym_base is used to map the fdr relative indices which
+ appear in the file to the position number which we are
+ using. */
+ sym_base = ecoffsymbol (symbol)->fdr->isymBase;
+ if (ecoffsymbol (symbol)->local)
+ sym_base += ecoff_data (abfd)->symbolic_header.iextMax;
+
+ /* aux_base is the start of the aux entries for this file;
+ asym.index is an offset from this. */
+ aux_base = (ecoff_data (abfd)->external_aux
+ + ecoffsymbol (symbol)->fdr->iauxBase);
+
+ /* The aux entries are stored in host byte order; the
+ order is indicated by a bit in the fdr. */
+ bigendian = ecoffsymbol (symbol)->fdr->fBigendian;
+
+ /* This switch is basically from gcc/mips-tdump.c */
+ switch (ecoff_ext.asym.st)
+ {
+ case stNil:
+ case stLabel:
+ break;
+
+ case stFile:
+ case stBlock:
+ fprintf (file, "\n End+1 symbol: %ld",
+ (long) (indx + sym_base));
+ break;
+
+ case stEnd:
+ if (ecoff_ext.asym.sc == scText
+ || ecoff_ext.asym.sc == scInfo)
+ fprintf (file, "\n First symbol: %ld",
+ (long) (indx + sym_base));
+ else
+ fprintf (file, "\n First symbol: %ld",
+ (long) (AUX_GET_ISYM (bigendian,
+ &aux_base[ecoff_ext.asym.index])
+ + sym_base));
+ break;
+
+ case stProc:
+ case stStaticProc:
+ if (ECOFF_IS_STAB (&ecoff_ext.asym))
+ ;
+ else if (ecoffsymbol (symbol)->local)
+ fprintf (file, "\n End+1 symbol: %-7ld Type: %s",
+ (long) (AUX_GET_ISYM (bigendian,
+ &aux_base[ecoff_ext.asym.index])
+ + sym_base),
+ ecoff_type_to_string (abfd, aux_base, indx + 1,
+ bigendian));
+ else
+ fprintf (file, "\n Local symbol: %d",
+ (indx
+ + sym_base
+ + ecoff_data (abfd)->symbolic_header.iextMax));
+ break;
+
+ default:
+ if (! ECOFF_IS_STAB (&ecoff_ext.asym))
+ fprintf (file, "\n Type: %s",
+ ecoff_type_to_string (abfd, aux_base, indx,
+ bigendian));
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+/* Read in the relocs for a section. */
+
+static boolean
+ecoff_slurp_reloc_table (abfd, section, symbols)
+ bfd *abfd;
+ asection *section;
+ asymbol **symbols;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ arelent *internal_relocs;
+ bfd_size_type external_reloc_size;
+ bfd_size_type external_relocs_size;
+ char *external_relocs;
+ arelent *rptr;
+ unsigned int i;
+
+ if (section->relocation != (arelent *) NULL
+ || section->reloc_count == 0
+ || (section->flags & SEC_CONSTRUCTOR) != 0)
+ return true;
+
+ if (ecoff_slurp_symbol_table (abfd) == false)
+ return false;
+
+ internal_relocs = (arelent *) bfd_alloc (abfd,
+ (sizeof (arelent)
+ * section->reloc_count));
+ external_reloc_size = backend->external_reloc_size;
+ external_relocs_size = external_reloc_size * section->reloc_count;
+ external_relocs = (char *) bfd_alloc (abfd, external_relocs_size);
+ if (internal_relocs == (arelent *) NULL
+ || external_relocs == (char *) NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0)
+ return false;
+ if (bfd_read (external_relocs, 1, external_relocs_size, abfd)
+ != external_relocs_size)
+ {
+ bfd_error = system_call_error;
+ return false;
+ }
+
+ for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++)
+ {
+ struct internal_reloc intern;
+
+ (*backend->swap_reloc_in) (abfd,
+ external_relocs + i * external_reloc_size,
+ &intern);
+
+ if (intern.r_extern)
+ {
+ /* r_symndx is an index into the external symbols. */
+ BFD_ASSERT (intern.r_symndx >= 0
+ && (intern.r_symndx
+ < ecoff_data (abfd)->symbolic_header.iextMax));
+ rptr->sym_ptr_ptr = symbols + intern.r_symndx;
+ rptr->addend = 0;
+ }
+ else if (intern.r_symndx == RELOC_SECTION_NONE
+ || intern.r_symndx == RELOC_SECTION_ABS)
+ {
+ rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ rptr->addend = 0;
+ }
+ else
+ {
+ CONST char *sec_name;
+ asection *sec;
+
+ /* r_symndx is a section key. */
+ switch (intern.r_symndx)
+ {
+ case RELOC_SECTION_TEXT: sec_name = ".text"; break;
+ case RELOC_SECTION_RDATA: sec_name = ".rdata"; break;
+ case RELOC_SECTION_DATA: sec_name = ".data"; break;
+ case RELOC_SECTION_SDATA: sec_name = ".sdata"; break;
+ case RELOC_SECTION_SBSS: sec_name = ".sbss"; break;
+ case RELOC_SECTION_BSS: sec_name = ".bss"; break;
+ case RELOC_SECTION_INIT: sec_name = ".init"; break;
+ case RELOC_SECTION_LIT8: sec_name = ".lit8"; break;
+ case RELOC_SECTION_LIT4: sec_name = ".lit4"; break;
+ case RELOC_SECTION_XDATA: sec_name = ".xdata"; break;
+ case RELOC_SECTION_PDATA: sec_name = ".pdata"; break;
+ case RELOC_SECTION_LITA: sec_name = ".lita"; break;
+ default: abort ();
+ }
+
+ sec = bfd_get_section_by_name (abfd, sec_name);
+ if (sec == (asection *) NULL)
+ abort ();
+ rptr->sym_ptr_ptr = sec->symbol_ptr_ptr;
+
+ rptr->addend = - bfd_get_section_vma (abfd, sec);
+ }
+
+ rptr->address = intern.r_vaddr - bfd_get_section_vma (abfd, section);
+
+ /* Let the backend select the howto field and do any other
+ required processing. */
+ (*backend->finish_reloc) (abfd, &intern, rptr);
+ }
+
+ bfd_release (abfd, external_relocs);
+
+ section->relocation = internal_relocs;
+
+ return true;
+}
+
+/* Get a canonical list of relocs. */
+
+unsigned int
+ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
+ bfd *abfd;
+ asection *section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ unsigned int count;
+
+ if (section->flags & SEC_CONSTRUCTOR)
+ {
+ arelent_chain *chain;
+
+ /* This section has relocs made up by us, not the file, so take
+ them out of their chain and place them into the data area
+ provided. */
+ for (count = 0, chain = section->constructor_chain;
+ count < section->reloc_count;
+ count++, chain = chain->next)
+ *relptr++ = &chain->relent;
+ }
+ else
+ {
+ arelent *tblptr;
+
+ if (ecoff_slurp_reloc_table (abfd, section, symbols) == false)
+ return 0;
+
+ tblptr = section->relocation;
+ if (tblptr == (arelent *) NULL)
+ return 0;
+
+ for (count = 0; count < section->reloc_count; count++)
+ *relptr++ = tblptr++;
+ }
+
+ *relptr = (arelent *) NULL;
+
+ 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. */
+
+boolean
+ecoff_find_nearest_line (abfd,
+ section,
+ ignore_symbols,
+ offset,
+ filename_ptr,
+ functionname_ptr,
+ retline_ptr)
+ bfd *abfd;
+ asection *section;
+ asymbol **ignore_symbols;
+ bfd_vma offset;
+ CONST char **filename_ptr;
+ CONST char **functionname_ptr;
+ unsigned int *retline_ptr;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ FDR *fdr_ptr;
+ FDR *fdr_start;
+ FDR *fdr_end;
+ FDR *fdr_hold;
+ bfd_size_type external_pdr_size;
+ char *pdr_ptr;
+ char *pdr_end;
+ PDR pdr;
+ unsigned char *line_ptr;
+ unsigned char *line_end;
+ int lineno;
+
+ /* If we're not in the .text section, we don't have any line
+ numbers. */
+ if (strcmp (section->name, _TEXT) != 0
+ || offset < ecoff_data (abfd)->text_start
+ || offset >= ecoff_data (abfd)->text_end)
+ return false;
+
+ /* Make sure we have the FDR's. */
+ if (ecoff_slurp_symbolic_info (abfd) == false
+ || bfd_get_symcount (abfd) == 0)
+ return false;
+
+ /* Each file descriptor (FDR) has a memory address. Here we track
+ down which FDR we want. The FDR's are stored in increasing
+ memory order. If speed is ever important, this can become a
+ binary search. We must ignore FDR's with no PDR entries; they
+ will have the adr of the FDR before or after them. */
+ fdr_start = ecoff_data (abfd)->fdr;
+ fdr_end = fdr_start + ecoff_data (abfd)->symbolic_header.ifdMax;
+ fdr_hold = (FDR *) NULL;
+ for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
+ {
+ if (fdr_ptr->cpd == 0)
+ continue;
+ if (offset < fdr_ptr->adr)
+ break;
+ fdr_hold = fdr_ptr;
+ }
+ if (fdr_hold == (FDR *) NULL)
+ return false;
+ fdr_ptr = fdr_hold;
+
+ /* Each FDR has a list of procedure descriptors (PDR). PDR's also
+ have an address, which is relative to the FDR address, and are
+ also stored in increasing memory order. */
+ offset -= fdr_ptr->adr;
+ external_pdr_size = backend->external_pdr_size;
+ pdr_ptr = ((char *) ecoff_data (abfd)->external_pdr
+ + fdr_ptr->ipdFirst * external_pdr_size);
+ pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
+ (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+
+ /* The address of the first PDR is an offset which applies to the
+ addresses of all the PDR's. */
+ offset += pdr.adr;
+
+ for (pdr_ptr += external_pdr_size;
+ pdr_ptr < pdr_end;
+ pdr_ptr += external_pdr_size)
+ {
+ (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+ if (offset < pdr.adr)
+ break;
+ }
+
+ /* Now we can look for the actual line number. The line numbers are
+ stored in a very funky format, which I won't try to describe.
+ Note that right here pdr_ptr and pdr hold the PDR *after* the one
+ we want; we need this to compute line_end. */
+ line_end = ecoff_data (abfd)->line;
+ if (pdr_ptr == pdr_end)
+ line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
+ else
+ line_end += fdr_ptr->cbLineOffset + pdr.cbLineOffset;
+
+ /* Now change pdr and pdr_ptr to the one we want. */
+ pdr_ptr -= external_pdr_size;
+ (*backend->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+
+ offset -= pdr.adr;
+ lineno = pdr.lnLow;
+ line_ptr = (ecoff_data (abfd)->line
+ + fdr_ptr->cbLineOffset
+ + pdr.cbLineOffset);
+ while (line_ptr < line_end)
+ {
+ int delta;
+ int count;
+
+ delta = *line_ptr >> 4;
+ if (delta >= 0x8)
+ delta -= 0x10;
+ count = (*line_ptr & 0xf) + 1;
+ ++line_ptr;
+ if (delta == -8)
+ {
+ delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
+ if (delta >= 0x8000)
+ delta -= 0x10000;
+ line_ptr += 2;
+ }
+ lineno += delta;
+ if (offset < count * 4)
+ break;
+ offset -= count * 4;
+ }
+
+ /* If fdr_ptr->rss is -1, then this file does not have full symbols,
+ at least according to gdb/mipsread.c. */
+ if (fdr_ptr->rss == -1)
+ {
+ *filename_ptr = NULL;
+ if (pdr.isym == -1)
+ *functionname_ptr = NULL;
+ else
+ {
+ EXTR proc_ext;
+
+ (*backend->swap_ext_in) (abfd,
+ ((char *) ecoff_data (abfd)->external_ext
+ + pdr.isym * backend->external_ext_size),
+ &proc_ext);
+ *functionname_ptr = ecoff_data (abfd)->ssext + proc_ext.asym.iss;
+ }
+ }
+ else
+ {
+ SYMR proc_sym;
+
+ *filename_ptr = ecoff_data (abfd)->ss + fdr_ptr->issBase + fdr_ptr->rss;
+ (*backend->swap_sym_in) (abfd,
+ ((char *) ecoff_data (abfd)->external_sym
+ + ((fdr_ptr->isymBase + pdr.isym)
+ * backend->external_sym_size)),
+ &proc_sym);
+ *functionname_ptr = (ecoff_data (abfd)->ss
+ + fdr_ptr->issBase
+ + proc_sym.iss);
+ }
+ if (lineno == ilineNil)
+ lineno = 0;
+ *retline_ptr = lineno;
+ return true;
+}
+
+/* We can't use the generic linking routines for ECOFF, because we
+ have to handle all the debugging information. The generic link
+ routine just works out the section contents and attaches a list of
+ symbols.
+
+ We link by looping over all the seclets. We make two passes. On
+ the first we set the actual section contents and determine the size
+ of the debugging information. On the second we accumulate the
+ debugging information and write it out.
+
+ This currently always accumulates the debugging information, which
+ is incorrect, because it ignores the -s and -S options of the
+ linker. The linker needs to be modified to give us that
+ information in a more useful format (currently it just provides a
+ list of symbols which should appear in the output file). */
+
+/* Clear the output_has_begun flag for all the input BFD's. We use it
+ to avoid linking in the debugging information for a BFD more than
+ once. */
+
+static void
+ecoff_clear_output_flags (abfd)
+ bfd *abfd;
+{
+ register asection *o;
+ register bfd_seclet_type *p;
+
+ for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ for (p = o->seclets_head;
+ p != (bfd_seclet_type *) NULL;
+ p = p->next)
+ if (p->type == bfd_indirect_seclet)
+ p->u.indirect.section->owner->output_has_begun = false;
+}
+
+/* Handle an indirect seclet on the first pass. Set the contents of
+ the output section, and accumulate the debugging information if
+ any. */
+
+static boolean
+ecoff_rel (output_bfd, seclet, output_section, data, relocateable)
+ bfd *output_bfd;
+ bfd_seclet_type *seclet;
+ asection *output_section;
+ PTR data;
+ boolean relocateable;
+{
+ bfd *input_bfd;
+ HDRR *output_symhdr;
+ HDRR *input_symhdr;
+
+ if ((output_section->flags & SEC_HAS_CONTENTS)
+ && !(output_section->flags & SEC_NEVER_LOAD)
+ && (output_section->flags & SEC_LOAD)
+ && seclet->size)
+ {
+ data = (PTR) bfd_get_relocated_section_contents (output_bfd,
+ seclet,
+ data,
+ relocateable);
+ if (bfd_set_section_contents (output_bfd,
+ output_section,
+ data,
+ seclet->offset,
+ seclet->size)
+ == false)
+ {
+ abort();
+ }
+ }
+
+ input_bfd = seclet->u.indirect.section->owner;
+
+ /* We want to figure out how much space will be required to
+ incorporate all the debugging information from input_bfd. We use
+ the output_has_begun field to avoid adding it in more than once.
+ The actual incorporation is done in the second pass, in
+ ecoff_get_debug. The code has to parallel that code in its
+ manipulations of output_symhdr. */
+
+ if (input_bfd->output_has_begun)
+ return true;
+ input_bfd->output_has_begun = true;
+
+ output_symhdr = &ecoff_data (output_bfd)->symbolic_header;
+
+ if (input_bfd->xvec->flavour != bfd_target_ecoff_flavour)
+ {
+ asymbol **symbols;
+ asymbol **sym_ptr;
+ asymbol **sym_end;
+
+ /* We just accumulate local symbols from a non-ECOFF BFD. The
+ external symbols are handled separately. */
+
+ symbols = (asymbol **) bfd_alloc (output_bfd,
+ get_symtab_upper_bound (input_bfd));
+ if (symbols == (asymbol **) NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols);
+
+ for (sym_ptr = symbols; sym_ptr < sym_end; sym_ptr++)
+ {
+ size_t len;
+
+ len = strlen ((*sym_ptr)->name);
+ if (((*sym_ptr)->flags & BSF_EXPORT) == 0)
+ {
+ ++output_symhdr->isymMax;
+ output_symhdr->issMax += len + 1;
+ }
+ }
+
+ bfd_release (output_bfd, (PTR) symbols);
+
+ ++output_symhdr->ifdMax;
+
+ return true;
+ }
+
+ /* We simply add in the information from another ECOFF BFD. First
+ we make sure we have the symbolic information. */
+ if (ecoff_slurp_symbol_table (input_bfd) == false)
+ return false;
+ if (bfd_get_symcount (input_bfd) == 0)
+ return true;
+
+ input_symhdr = &ecoff_data (input_bfd)->symbolic_header;
+
+ /* Figure out how much information we are going to be putting in.
+ The external symbols are handled separately. */
+ output_symhdr->ilineMax += input_symhdr->ilineMax;
+ output_symhdr->cbLine += input_symhdr->cbLine;
+ output_symhdr->idnMax += input_symhdr->idnMax;
+ output_symhdr->ipdMax += input_symhdr->ipdMax;
+ output_symhdr->isymMax += input_symhdr->isymMax;
+ output_symhdr->ioptMax += input_symhdr->ioptMax;
+ output_symhdr->iauxMax += input_symhdr->iauxMax;
+ output_symhdr->issMax += input_symhdr->issMax;
+ output_symhdr->ifdMax += input_symhdr->ifdMax;
+
+ /* The RFD's are special, since we create them if needed. */
+ if (input_symhdr->crfd > 0)
+ output_symhdr->crfd += input_symhdr->crfd;
+ else
+ output_symhdr->crfd += input_symhdr->ifdMax;
+
+ return true;
+}
+
+/* Handle an arbitrary seclet on the first pass. */
+
+static boolean
+ecoff_dump_seclet (abfd, seclet, section, data, relocateable)
+ bfd *abfd;
+ bfd_seclet_type *seclet;
+ asection *section;
+ PTR data;
+ boolean relocateable;
+{
+ switch (seclet->type)
+ {
+ case bfd_indirect_seclet:
+ /* The contents of this section come from another one somewhere
+ else. */
+ return ecoff_rel (abfd, seclet, section, data, relocateable);
+
+ case bfd_fill_seclet:
+ /* Fill in the section with fill.value. This is used to pad out
+ sections, but we must avoid padding the .bss section. */
+ if ((section->flags & SEC_HAS_CONTENTS) == 0)
+ {
+ if (seclet->u.fill.value != 0)
+ abort ();
+ }
+ else
+ {
+ char *d = (char *) bfd_alloc (abfd, seclet->size);
+ unsigned int i;
+ boolean ret;
+
+ for (i = 0; i < seclet->size; i+=2)
+ d[i] = seclet->u.fill.value >> 8;
+ for (i = 1; i < seclet->size; i+=2)
+ d[i] = seclet->u.fill.value;
+ ret = bfd_set_section_contents (abfd, section, d, seclet->offset,
+ seclet->size);
+ bfd_release (abfd, (PTR) d);
+ return ret;
+ }
+ break;
+
+ default:
+ abort();
+ }
+
+ return true;
+}
+
+/* Add a string to the debugging information we are accumulating for a
+ file. Return the offset from the fdr string base or from the
+ external string base. */
+
+static long
+ecoff_add_string (output_bfd, fdr, string, external)
+ bfd *output_bfd;
+ FDR *fdr;
+ CONST char *string;
+ boolean external;
+{
+ HDRR *symhdr;
+ size_t len;
+ long ret;
+
+ symhdr = &ecoff_data (output_bfd)->symbolic_header;
+ len = strlen (string);
+ if (external)
+ {
+ strcpy (ecoff_data (output_bfd)->ssext + symhdr->issExtMax, string);
+ ret = symhdr->issExtMax;
+ symhdr->issExtMax += len + 1;
+ }
+ else
+ {
+ strcpy (ecoff_data (output_bfd)->ss + symhdr->issMax, string);
+ ret = fdr->cbSs;
+ symhdr->issMax += len + 1;
+ fdr->cbSs += len + 1;
+ }
+ return ret;
+}
+
+/* Accumulate the debugging information from an input section. */
+
+static boolean
+ecoff_get_debug (output_bfd, seclet, section, relocateable)
+ bfd *output_bfd;
+ bfd_seclet_type *seclet;
+ asection *section;
+ boolean relocateable;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (output_bfd);
+ const bfd_size_type external_sym_size = backend->external_sym_size;
+ const bfd_size_type external_pdr_size = backend->external_pdr_size;
+ const bfd_size_type external_fdr_size = backend->external_fdr_size;
+ const bfd_size_type external_rfd_size = backend->external_rfd_size;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = backend->swap_sym_in;
+ void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
+ = backend->swap_sym_out;
+ void (* const swap_pdr_in) PARAMS ((bfd *, PTR, PDR *))
+ = backend->swap_pdr_in;
+ void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR))
+ = backend->swap_fdr_out;
+ void (* const swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR))
+ = backend->swap_rfd_out;
+ bfd *input_bfd;
+ HDRR *output_symhdr;
+ HDRR *input_symhdr;
+ ecoff_data_type *output_ecoff;
+ ecoff_data_type *input_ecoff;
+ unsigned int count;
+ char *sym_out;
+ ecoff_symbol_type *esym_ptr;
+ ecoff_symbol_type *esym_end;
+ FDR *fdr_ptr;
+ FDR *fdr_end;
+ char *fdr_out;
+
+ input_bfd = seclet->u.indirect.section->owner;
+
+ /* Don't get the information more than once. */
+ if (input_bfd->output_has_begun)
+ return true;
+ input_bfd->output_has_begun = true;
+
+ output_ecoff = ecoff_data (output_bfd);
+ output_symhdr = &output_ecoff->symbolic_header;
+
+ if (input_bfd->xvec->flavour != bfd_target_ecoff_flavour)
+ {
+ FDR fdr;
+ asymbol **symbols;
+ asymbol **sym_ptr;
+ asymbol **sym_end;
+
+ /* This is not an ECOFF BFD. Just gather the symbols. */
+
+ memset (&fdr, 0, sizeof fdr);
+
+ fdr.adr = bfd_get_section_vma (output_bfd, section) + seclet->offset;
+ fdr.issBase = output_symhdr->issMax;
+ fdr.cbSs = 0;
+ fdr.rss = ecoff_add_string (output_bfd,
+ &fdr,
+ bfd_get_filename (input_bfd),
+ false);
+ fdr.isymBase = output_symhdr->isymMax;
+
+ /* Get the local symbols from the input BFD. */
+ symbols = (asymbol **) bfd_alloc (output_bfd,
+ get_symtab_upper_bound (input_bfd));
+ if (symbols == (asymbol **) NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ sym_end = symbols + bfd_canonicalize_symtab (input_bfd, symbols);
+
+ /* Handle the local symbols. Any external symbols are handled
+ separately. */
+ fdr.csym = 0;
+ for (sym_ptr = symbols; sym_ptr != sym_end; sym_ptr++)
+ {
+ SYMR internal_sym;
+
+ if (((*sym_ptr)->flags & BSF_EXPORT) != 0)
+ continue;
+ memset (&internal_sym, 0, sizeof internal_sym);
+ internal_sym.iss = ecoff_add_string (output_bfd,
+ &fdr,
+ (*sym_ptr)->name,
+ false);
+
+ if (bfd_is_com_section ((*sym_ptr)->section)
+ || (*sym_ptr)->section == &bfd_und_section)
+ internal_sym.value = (*sym_ptr)->value;
+ else
+ internal_sym.value = ((*sym_ptr)->value
+ + (*sym_ptr)->section->output_offset
+ + (*sym_ptr)->section->output_section->vma);
+ internal_sym.st = stNil;
+ internal_sym.sc = scUndefined;
+ internal_sym.index = indexNil;
+ (*swap_sym_out) (output_bfd, &internal_sym,
+ ((char *) output_ecoff->external_sym
+ + output_symhdr->isymMax * external_sym_size));
+ ++fdr.csym;
+ ++output_symhdr->isymMax;
+ }
+
+ bfd_release (output_bfd, (PTR) symbols);
+
+ /* Leave everything else in the FDR zeroed out. This will cause
+ the lang field to be langC. The fBigendian field will
+ indicate little endian format, but it doesn't matter because
+ it only applies to aux fields and there are none. */
+
+ (*swap_fdr_out) (output_bfd, &fdr,
+ ((char *) output_ecoff->external_fdr
+ + output_symhdr->ifdMax * external_fdr_size));
+ ++output_symhdr->ifdMax;
+ return true;
+ }
+
+ /* This is an ECOFF BFD. We want to grab the information from
+ input_bfd and attach it to output_bfd. */
+ count = bfd_get_symcount (input_bfd);
+ if (count == 0)
+ return true;
+ input_ecoff = ecoff_data (input_bfd);
+ input_symhdr = &input_ecoff->symbolic_header;
+
+ /* I think that it is more efficient to simply copy the debugging
+ information from the input BFD to the output BFD. Because ECOFF
+ uses relative pointers for most of the debugging information,
+ only a little of it has to be changed at all. */
+
+ /* Swap in the local symbols, adjust their values, and swap them out
+ again. The external symbols are handled separately. */
+ sym_out = ((char *) output_ecoff->external_sym
+ + output_symhdr->isymMax * external_sym_size);
+
+ esym_ptr = ecoff_data (input_bfd)->canonical_symbols;
+ esym_end = esym_ptr + count;
+ for (; esym_ptr < esym_end; esym_ptr++)
+ {
+ if (esym_ptr->local)
+ {
+ SYMR sym;
+
+ (*swap_sym_in) (input_bfd, esym_ptr->native, &sym);
+
+ /* If we're producing an executable, move common symbols
+ into bss. */
+ if (relocateable == false)
+ {
+ if (sym.sc == scCommon)
+ sym.sc = scBss;
+ else if (sym.sc == scSCommon)
+ sym.sc = scSBss;
+ }
+
+ if (! bfd_is_com_section (esym_ptr->symbol.section)
+ && (esym_ptr->symbol.flags & BSF_DEBUGGING) == 0
+ && esym_ptr->symbol.section != &bfd_und_section)
+ sym.value = (esym_ptr->symbol.value
+ + esym_ptr->symbol.section->output_offset
+ + esym_ptr->symbol.section->output_section->vma);
+ (*swap_sym_out) (output_bfd, &sym, sym_out);
+ sym_out += external_sym_size;
+ }
+ }
+
+ /* That should have accounted for all the local symbols in
+ input_bfd. */
+
+ /* Copy the information that does not need swapping. */
+ memcpy (output_ecoff->line + output_symhdr->cbLine,
+ input_ecoff->line,
+ input_symhdr->cbLine * sizeof (unsigned char));
+ memcpy (output_ecoff->external_aux + output_symhdr->iauxMax,
+ input_ecoff->external_aux,
+ input_symhdr->iauxMax * sizeof (union aux_ext));
+ memcpy (output_ecoff->ss + output_symhdr->issMax,
+ input_ecoff->ss,
+ input_symhdr->issMax * sizeof (char));
+
+ /* Some of the information may need to be swapped. */
+ if (output_bfd->xvec->header_byteorder_big_p
+ == input_bfd->xvec->header_byteorder_big_p)
+ {
+ /* The two BFD's have the same endianness, so memcpy will
+ suffice. */
+ if (input_symhdr->idnMax > 0)
+ memcpy (((char *) output_ecoff->external_dnr
+ + output_symhdr->idnMax * backend->external_dnr_size),
+ input_ecoff->external_dnr,
+ input_symhdr->idnMax * backend->external_dnr_size);
+ if (input_symhdr->ipdMax > 0)
+ memcpy (((char *) output_ecoff->external_pdr
+ + output_symhdr->ipdMax * external_pdr_size),
+ input_ecoff->external_pdr,
+ input_symhdr->ipdMax * external_pdr_size);
+ if (input_symhdr->ioptMax > 0)
+ memcpy (((char *) output_ecoff->external_opt
+ + output_symhdr->ioptMax * backend->external_opt_size),
+ input_ecoff->external_opt,
+ input_symhdr->ioptMax * backend->external_opt_size);
+ }
+ else
+ {
+ bfd_size_type sz;
+ char *in;
+ char *end;
+ char *out;
+
+ /* The two BFD's have different endianness, so we must swap
+ everything in and out. This code would always work, but it
+ would be slow in the normal case. */
+ sz = backend->external_dnr_size;
+ in = (char *) input_ecoff->external_dnr;
+ end = in + input_symhdr->idnMax * sz;
+ out = (char *) output_ecoff->external_dnr + output_symhdr->idnMax * sz;
+ for (; in < end; in += sz, out += sz)
+ {
+ DNR dnr;
+
+ (*backend->swap_dnr_in) (input_bfd, in, &dnr);
+ (*backend->swap_dnr_out) (output_bfd, &dnr, out);
+ }
+
+ sz = external_pdr_size;
+ in = (char *) input_ecoff->external_pdr;
+ end = in + input_symhdr->ipdMax * sz;
+ out = (char *) output_ecoff->external_pdr + output_symhdr->ipdMax * sz;
+ for (; in < end; in += sz, out += sz)
+ {
+ PDR pdr;
+
+ (*swap_pdr_in) (input_bfd, in, &pdr);
+ (*backend->swap_pdr_out) (output_bfd, &pdr, out);
+ }
+
+ sz = backend->external_opt_size;
+ in = (char *) input_ecoff->external_opt;
+ end = in + input_symhdr->ioptMax * sz;
+ out = (char *) output_ecoff->external_opt + output_symhdr->ioptMax * sz;
+ for (; in < end; in += sz, out += sz)
+ {
+ OPTR opt;
+
+ (*backend->swap_opt_in) (input_bfd, in, &opt);
+ (*backend->swap_opt_out) (output_bfd, &opt, out);
+ }
+ }
+
+ /* Set ifdbase so that the external symbols know how to adjust their
+ ifd values. */
+ input_ecoff->ifdbase = output_symhdr->ifdMax;
+
+ fdr_ptr = input_ecoff->fdr;
+ fdr_end = fdr_ptr + input_symhdr->ifdMax;
+ fdr_out = ((char *) output_ecoff->external_fdr
+ + output_symhdr->ifdMax * external_fdr_size);
+ for (; fdr_ptr < fdr_end; fdr_ptr++, fdr_out += external_fdr_size)
+ {
+ FDR fdr;
+ unsigned long pdr_off;
+
+ fdr = *fdr_ptr;
+
+ /* The memory address for this fdr is the address for the seclet
+ plus the offset to this fdr within input_bfd. For some
+ reason the offset of the first procedure pointer is also
+ added in. */
+ if (fdr.cpd == 0)
+ pdr_off = 0;
+ else
+ {
+ PDR pdr;
+
+ (*swap_pdr_in) (input_bfd,
+ ((char *) input_ecoff->external_pdr
+ + fdr.ipdFirst * external_pdr_size),
+ &pdr);
+ pdr_off = pdr.adr;
+ }
+ fdr.adr = (bfd_get_section_vma (output_bfd, section)
+ + seclet->offset
+ + (fdr_ptr->adr - input_ecoff->fdr->adr)
+ + pdr_off);
+
+ fdr.issBase += output_symhdr->issMax;
+ fdr.isymBase += output_symhdr->isymMax;
+ fdr.ilineBase += output_symhdr->ilineMax;
+ fdr.ioptBase += output_symhdr->ioptMax;
+ fdr.ipdFirst += output_symhdr->ipdMax;
+ fdr.iauxBase += output_symhdr->iauxMax;
+ fdr.rfdBase += output_symhdr->crfd;
+
+ /* If there are no RFD's, we are going to add some. We don't
+ want to adjust irfd for this, so that all the FDR's can share
+ the RFD's. */
+ if (input_symhdr->crfd == 0)
+ fdr.crfd = input_symhdr->ifdMax;
+
+ if (fdr.cbLine != 0)
+ fdr.cbLineOffset += output_symhdr->cbLine;
+
+ (*swap_fdr_out) (output_bfd, &fdr, fdr_out);
+ }
+
+ if (input_symhdr->crfd > 0)
+ {
+ void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *))
+ = backend->swap_rfd_in;
+ char *rfd_in;
+ char *rfd_end;
+ char *rfd_out;
+
+ /* Swap and adjust the RFD's. RFD's are only created by the
+ linker, so this will only be necessary if one of the input
+ files is the result of a partial link. Presumably all
+ necessary RFD's are present. */
+ rfd_in = (char *) input_ecoff->external_rfd;
+ rfd_end = rfd_in + input_symhdr->crfd * external_rfd_size;
+ rfd_out = ((char *) output_ecoff->external_rfd
+ + output_symhdr->crfd * external_rfd_size);
+ for (;
+ rfd_in < rfd_end;
+ rfd_in += external_rfd_size, rfd_out += external_rfd_size)
+ {
+ RFDT rfd;
+
+ (*swap_rfd_in) (input_bfd, rfd_in, &rfd);
+ rfd += output_symhdr->ifdMax;
+ (*swap_rfd_out) (output_bfd, &rfd, rfd_out);
+ }
+ output_symhdr->crfd += input_symhdr->crfd;
+ }
+ else
+ {
+ char *rfd_out;
+ char *rfd_end;
+ RFDT rfd;
+
+ /* Create RFD's. Some of the debugging information includes
+ relative file indices. These indices are taken as indices to
+ the RFD table if there is one, or to the global table if
+ there is not. If we did not create RFD's, we would have to
+ parse and adjust all the debugging information which contains
+ file indices. */
+ rfd = output_symhdr->ifdMax;
+ rfd_out = ((char *) output_ecoff->external_rfd
+ + output_symhdr->crfd * external_rfd_size);
+ rfd_end = rfd_out + input_symhdr->ifdMax * external_rfd_size;
+ for (; rfd_out < rfd_end; rfd_out += external_rfd_size, rfd++)
+ (*swap_rfd_out) (output_bfd, &rfd, rfd_out);
+ output_symhdr->crfd += input_symhdr->ifdMax;
+ }
+
+ /* Combine the register masks. Not all of these are used on all
+ targets, but that's OK because only the relevant ones will be
+ swapped in and out. */
+ {
+ int i;
+
+ output_ecoff->gprmask |= input_ecoff->gprmask;
+ output_ecoff->fprmask |= input_ecoff->fprmask;
+ for (i = 0; i < 4; i++)
+ output_ecoff->cprmask[i] |= input_ecoff->cprmask[i];
+ }
+
+ /* Update the counts. */
+ output_symhdr->ilineMax += input_symhdr->ilineMax;
+ output_symhdr->cbLine += input_symhdr->cbLine;
+ output_symhdr->idnMax += input_symhdr->idnMax;
+ output_symhdr->ipdMax += input_symhdr->ipdMax;
+ output_symhdr->isymMax += input_symhdr->isymMax;
+ output_symhdr->ioptMax += input_symhdr->ioptMax;
+ output_symhdr->iauxMax += input_symhdr->iauxMax;
+ output_symhdr->issMax += input_symhdr->issMax;
+ output_symhdr->ifdMax += input_symhdr->ifdMax;
+
+ return true;
+}
+
+/* This is the actual link routine. It makes two passes over all the
+ seclets. */
+
+boolean
+ecoff_bfd_seclet_link (abfd, data, relocateable)
+ bfd *abfd;
+ PTR data;
+ boolean relocateable;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ HDRR *symhdr;
+ int ipass;
+ register asection *o;
+ register bfd_seclet_type *p;
+ asymbol **sym_ptr_ptr;
+ bfd_size_type debug_align;
+ bfd_size_type size;
+ char *raw;
+
+ /* We accumulate the debugging information counts in the symbolic
+ header. */
+ symhdr = &ecoff_data (abfd)->symbolic_header;
+ symhdr->magic = backend->sym_magic;
+ /* FIXME: What should the version stamp be? */
+ symhdr->vstamp = 0;
+ symhdr->ilineMax = 0;
+ symhdr->cbLine = 0;
+ symhdr->idnMax = 0;
+ symhdr->ipdMax = 0;
+ symhdr->isymMax = 0;
+ symhdr->ioptMax = 0;
+ symhdr->iauxMax = 0;
+ symhdr->issMax = 0;
+ symhdr->issExtMax = 0;
+ symhdr->ifdMax = 0;
+ symhdr->crfd = 0;
+ symhdr->iextMax = 0;
+
+ /* We need to copy over the debugging symbols from each input BFD.
+ When we do this copying, we have to adjust the text address in
+ the FDR structures, so we have to know the text address used for
+ the input BFD. Since we only want to copy the symbols once per
+ input BFD, but we are going to look at each input BFD multiple
+ times (once for each section it provides), we arrange to always
+ look at the text section first. That means that when we copy the
+ debugging information, we always know the text address. So we
+ actually do each pass in two sub passes; first the text sections,
+ then the non-text sections. We use the output_has_begun flag to
+ determine whether we have copied over the debugging information
+ yet. */
+
+ /* Do the first pass: set the output section contents and count the
+ debugging information. */
+ ecoff_clear_output_flags (abfd);
+ for (ipass = 0; ipass < 2; ipass++)
+ {
+ for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ {
+ /* If this is a fake section, just forget it. The register
+ information is handled in another way. */
+ if (strcmp (o->name, SCOMMON) == 0
+ || strcmp (o->name, REGINFO) == 0)
+ continue;
+
+ /* For SEC_CODE sections, (flags & SEC_CODE) == 0 is false,
+ so they are done on pass 0. For other sections the
+ expression is true, so they are done on pass 1. */
+ if (((o->flags & SEC_CODE) == 0) != ipass)
+ continue;
+
+ for (p = o->seclets_head;
+ p != (bfd_seclet_type *) NULL;
+ p = p->next)
+ {
+ if (ecoff_dump_seclet (abfd, p, o, data, relocateable)
+ == false)
+ return false;
+ }
+ }
+ }
+
+ /* We handle the external symbols differently. We use the ones
+ attached to the output_bfd. The linker will have already
+ determined which symbols are to be attached. Here we just
+ determine how much space we will need for them. */
+ sym_ptr_ptr = bfd_get_outsymbols (abfd);
+ if (sym_ptr_ptr != NULL)
+ {
+ asymbol **sym_end;
+
+ sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
+ for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
+ {
+ if (((*sym_ptr_ptr)->flags & BSF_DEBUGGING) == 0
+ && ((*sym_ptr_ptr)->flags & BSF_LOCAL) == 0)
+ {
+ ++symhdr->iextMax;
+ symhdr->issExtMax += strlen ((*sym_ptr_ptr)->name) + 1;
+ }
+ }
+ }
+
+ /* Adjust the counts so that structures are longword aligned. */
+ debug_align = backend->debug_align;
+ --debug_align;
+ symhdr->cbLine = (symhdr->cbLine + debug_align) &~ debug_align;
+ symhdr->issMax = (symhdr->issMax + debug_align) &~ debug_align;
+ symhdr->issExtMax = (symhdr->issExtMax + debug_align) &~ debug_align;
+
+ /* Now the counts in symhdr are the correct size for the debugging
+ information. We allocate the right amount of space, and reset
+ the counts so that the second pass can use them as indices. It
+ would be possible to output the debugging information directly to
+ the file in pass 2, rather than to build it in memory and then
+ write it out. Outputting to the file would require a lot of
+ seeks and small writes, though, and I think this approach is
+ faster. */
+ size = (symhdr->cbLine * sizeof (unsigned char)
+ + symhdr->idnMax * backend->external_dnr_size
+ + symhdr->ipdMax * backend->external_pdr_size
+ + symhdr->isymMax * backend->external_sym_size
+ + symhdr->ioptMax * backend->external_opt_size
+ + symhdr->iauxMax * sizeof (union aux_ext)
+ + symhdr->issMax * sizeof (char)
+ + symhdr->issExtMax * sizeof (char)
+ + symhdr->ifdMax * backend->external_fdr_size
+ + symhdr->crfd * backend->external_rfd_size
+ + symhdr->iextMax * backend->external_ext_size);
+ raw = (char *) bfd_alloc (abfd, size);
+ if (raw == (char *) NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ ecoff_data (abfd)->raw_size = size;
+ ecoff_data (abfd)->raw_syments = (PTR) raw;
+
+ /* Initialize the raw pointers. */
+#define SET(field, count, type, size) \
+ ecoff_data (abfd)->field = (type) raw; \
+ raw += symhdr->count * size
+
+ SET (line, cbLine, unsigned char *, sizeof (unsigned char));
+ SET (external_dnr, idnMax, PTR, backend->external_dnr_size);
+ SET (external_pdr, ipdMax, PTR, backend->external_pdr_size);
+ SET (external_sym, isymMax, PTR, backend->external_sym_size);
+ SET (external_opt, ioptMax, PTR, backend->external_opt_size);
+ SET (external_aux, iauxMax, union aux_ext *, sizeof (union aux_ext));
+ SET (ss, issMax, char *, sizeof (char));
+ SET (ssext, issExtMax, char *, sizeof (char));
+ SET (external_fdr, ifdMax, PTR, backend->external_fdr_size);
+ SET (external_rfd, crfd, PTR, backend->external_rfd_size);
+ SET (external_ext, iextMax, PTR, backend->external_ext_size);
+#undef SET
+
+ /* Reset the counts so the second pass can use them to know how far
+ it has gotten. */
+ symhdr->ilineMax = 0;
+ symhdr->cbLine = 0;
+ symhdr->idnMax = 0;
+ symhdr->ipdMax = 0;
+ symhdr->isymMax = 0;
+ symhdr->ioptMax = 0;
+ symhdr->iauxMax = 0;
+ symhdr->issMax = 0;
+ symhdr->issExtMax = 0;
+ symhdr->ifdMax = 0;
+ symhdr->crfd = 0;
+ symhdr->iextMax = 0;
+
+ /* Do the second pass: accumulate the debugging information. */
+ ecoff_clear_output_flags (abfd);
+ for (ipass = 0; ipass < 2; ipass++)
+ {
+ for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ {
+ if (strcmp (o->name, SCOMMON) == 0
+ || strcmp (o->name, REGINFO) == 0)
+ continue;
+ if (((o->flags & SEC_CODE) == 0) != ipass)
+ continue;
+ for (p = o->seclets_head;
+ p != (bfd_seclet_type *) NULL;
+ p = p->next)
+ {
+ if (p->type == bfd_indirect_seclet)
+ {
+ if (ecoff_get_debug (abfd, p, o, relocateable) == false)
+ return false;
+ }
+ }
+ }
+ }
+
+ /* Put in the external symbols. */
+ sym_ptr_ptr = bfd_get_outsymbols (abfd);
+ if (sym_ptr_ptr != NULL)
+ {
+ const bfd_size_type external_ext_size = backend->external_ext_size;
+ void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *))
+ = backend->swap_ext_in;
+ void (* const swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR))
+ = backend->swap_ext_out;
+ char *ssext;
+ char *external_ext;
+
+ ssext = ecoff_data (abfd)->ssext;
+ external_ext = (char *) ecoff_data (abfd)->external_ext;
+ for (; *sym_ptr_ptr != NULL; sym_ptr_ptr++)
+ {
+ asymbol *sym_ptr;
+ EXTR esym;
+
+ sym_ptr = *sym_ptr_ptr;
+
+ if ((sym_ptr->flags & BSF_DEBUGGING) != 0
+ || (sym_ptr->flags & BSF_LOCAL) != 0)
+ continue;
+
+ /* The native pointer can be NULL for a symbol created by
+ the linker via ecoff_make_empty_symbol. */
+ if (bfd_asymbol_flavour (sym_ptr) != bfd_target_ecoff_flavour
+ || ecoffsymbol (sym_ptr)->native == NULL)
+ {
+ esym.jmptbl = 0;
+ esym.cobol_main = 0;
+ esym.weakext = 0;
+ esym.reserved = 0;
+ esym.ifd = ifdNil;
+ /* FIXME: we can do better than this for st and sc. */
+ esym.asym.st = stGlobal;
+ esym.asym.sc = scAbs;
+ esym.asym.reserved = 0;
+ esym.asym.index = indexNil;
+ }
+ else
+ {
+ ecoff_symbol_type *ecoff_sym_ptr;
+
+ ecoff_sym_ptr = ecoffsymbol (sym_ptr);
+ if (ecoff_sym_ptr->local)
+ abort ();
+ (*swap_ext_in) (abfd, ecoff_sym_ptr->native, &esym);
+
+ /* If we're producing an executable, move common symbols
+ into bss. */
+ if (relocateable == false)
+ {
+ if (esym.asym.sc == scCommon)
+ esym.asym.sc = scBss;
+ else if (esym.asym.sc == scSCommon)
+ esym.asym.sc = scSBss;
+ }
+
+ /* Adjust the FDR index for the symbol by that used for
+ the input BFD. */
+ esym.ifd += ecoff_data (bfd_asymbol_bfd (sym_ptr))->ifdbase;
+ }
+
+ esym.asym.iss = symhdr->issExtMax;
+
+ if (bfd_is_com_section (sym_ptr->section)
+ || sym_ptr->section == &bfd_und_section)
+ esym.asym.value = sym_ptr->value;
+ else
+ esym.asym.value = (sym_ptr->value
+ + sym_ptr->section->output_offset
+ + sym_ptr->section->output_section->vma);
+
+ (*swap_ext_out) (abfd, &esym, external_ext);
+
+ ecoff_set_sym_index (sym_ptr, symhdr->iextMax);
+
+ external_ext += external_ext_size;
+ ++symhdr->iextMax;
+
+ strcpy (ssext + symhdr->issExtMax, sym_ptr->name);
+ symhdr->issExtMax += strlen (sym_ptr->name) + 1;
+ }
+ }
+
+ /* Adjust the counts so that structures are longword aligned. */
+ symhdr->cbLine = (symhdr->cbLine + debug_align) &~ debug_align;
+ symhdr->issMax = (symhdr->issMax + debug_align) &~ debug_align;
+ symhdr->issExtMax = (symhdr->issExtMax + debug_align) &~ debug_align;
+
+ return true;
+}
+
+/* Set the architecture. The supported architecture is stored in the
+ backend pointer. We always set the architecture anyhow, since many
+ callers ignore the return value. */
+
+boolean
+ecoff_set_arch_mach (abfd, arch, machine)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ bfd_default_set_arch_mach (abfd, arch, machine);
+ return arch == ecoff_backend (abfd)->arch;
+}
+
+/* Get the size of the section headers. We do not output the .scommon
+ section which we created in ecoff_mkobject, nor do we output any
+ .reginfo section. */
+
+int
+ecoff_sizeof_headers (abfd, reloc)
+ bfd *abfd;
+ boolean reloc;
+{
+ asection *current;
+ int c;
+
+ c = 0;
+ for (current = abfd->sections;
+ current != (asection *)NULL;
+ current = current->next)
+ if (strcmp (current->name, SCOMMON) != 0
+ && strcmp (current->name, REGINFO) != 0)
+ ++c;
+
+ return (bfd_coff_filhsz (abfd)
+ + bfd_coff_aoutsz (abfd)
+ + c * bfd_coff_scnhsz (abfd));
+}
+
+
+/* Get the contents of a section. This is where we handle reading the
+ .reginfo section, which implicitly holds the contents of an
+ ecoff_reginfo structure. */
+
+boolean
+ecoff_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ ecoff_data_type *tdata = ecoff_data (abfd);
+ struct ecoff_reginfo s;
+ int i;
+
+ if (strcmp (section->name, REGINFO) != 0)
+ return bfd_generic_get_section_contents (abfd, section, location,
+ offset, count);
+
+ s.gp_value = tdata->gp;
+ s.gprmask = tdata->gprmask;
+ for (i = 0; i < 4; i++)
+ s.cprmask[i] = tdata->cprmask[i];
+ s.fprmask = tdata->fprmask;
+
+ /* bfd_get_section_contents has already checked that the offset and
+ size is reasonable. We don't have to worry about swapping or any
+ such thing; the .reginfo section is defined such that the
+ contents are an ecoff_reginfo structure as seen on the host. */
+ memcpy (location, ((char *) &s) + offset, count);
+ return true;
+}
+
+/* Calculate the file position for each section, and set
+ reloc_filepos. */
+
+static void
+ecoff_compute_section_file_positions (abfd)
+ bfd *abfd;
+{
+ asection *current;
+ file_ptr sofar;
+ file_ptr old_sofar;
+ boolean first_data;
+
+ if (bfd_get_start_address (abfd))
+ abfd->flags |= EXEC_P;
+
+ sofar = ecoff_sizeof_headers (abfd, false);
+
+ first_data = true;
+ for (current = abfd->sections;
+ current != (asection *) NULL;
+ current = current->next)
+ {
+ /* Only deal with sections which have contents */
+ if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0
+ || strcmp (current->name, SCOMMON) == 0
+ || strcmp (current->name, REGINFO) == 0)
+ continue;
+
+ /* On Ultrix, the data sections in an executable file must be
+ aligned to a page boundary within the file. This does not
+ affect the section size, though. FIXME: Does this work for
+ other platforms? */
+ if ((abfd->flags & EXEC_P) != 0
+ && (abfd->flags & D_PAGED) != 0
+ && first_data != false
+ && (current->flags & SEC_CODE) == 0)
+ {
+ const bfd_vma round = ecoff_backend (abfd)->round;
+
+ sofar = (sofar + round - 1) &~ (round - 1);
+ first_data = false;
+ }
+
+ /* Align the sections in the file to the same boundary on
+ which they are aligned in virtual memory. */
+ old_sofar = sofar;
+ sofar = BFD_ALIGN (sofar, 1 << current->alignment_power);
+
+ current->filepos = sofar;
+
+ sofar += current->_raw_size;
+
+ /* make sure that this section is of the right size too */
+ old_sofar = sofar;
+ sofar = BFD_ALIGN (sofar, 1 << current->alignment_power);
+ current->_raw_size += sofar - old_sofar;
+ }
+
+ ecoff_data (abfd)->reloc_filepos = sofar;
+}
+
+/* Set the contents of a section. This is where we handle setting the
+ contents of the .reginfo section, which implicitly holds a
+ ecoff_reginfo structure. */
+
+boolean
+ecoff_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (abfd->output_has_begun == false)
+ ecoff_compute_section_file_positions (abfd);
+
+ if (strcmp (section->name, REGINFO) == 0)
+ {
+ ecoff_data_type *tdata = ecoff_data (abfd);
+ struct ecoff_reginfo s;
+ int i;
+
+ /* If the caller is only changing part of the structure, we must
+ retrieve the current information before the memcpy. */
+ if (offset != 0 || count != sizeof (struct ecoff_reginfo))
+ {
+ s.gp_value = tdata->gp;
+ s.gprmask = tdata->gprmask;
+ for (i = 0; i < 4; i++)
+ s.cprmask[i] = tdata->cprmask[i];
+ s.fprmask = tdata->fprmask;
+ }
+
+ /* bfd_set_section_contents has already checked that the offset
+ and size is reasonable. We don't have to worry about
+ swapping or any such thing; the .reginfo section is defined
+ such that the contents are an ecoff_reginfo structure as seen
+ on the host. */
+ memcpy (((char *) &s) + offset, location, count);
+
+ tdata->gp = s.gp_value;
+ tdata->gprmask = s.gprmask;
+ for (i = 0; i < 4; i++)
+ tdata->cprmask[i] = s.cprmask[i];
+ tdata->fprmask = s.fprmask;
+
+ return true;
+
+ }
+
+ 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;
+}
+
+/* Write out an ECOFF file. */
+
+boolean
+ecoff_write_object_contents (abfd)
+ bfd *abfd;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ const bfd_vma round = backend->round;
+ const bfd_size_type filhsz = bfd_coff_filhsz (abfd);
+ const bfd_size_type aoutsz = bfd_coff_aoutsz (abfd);
+ const bfd_size_type scnhsz = bfd_coff_scnhsz (abfd);
+ const bfd_size_type external_hdr_size = backend->external_hdr_size;
+ const bfd_size_type external_reloc_size = backend->external_reloc_size;
+ void (* const swap_reloc_out) PARAMS ((bfd *,
+ const struct internal_reloc *,
+ PTR))
+ = backend->swap_reloc_out;
+ asection *current;
+ unsigned int count;
+ file_ptr scn_base;
+ file_ptr reloc_base;
+ file_ptr sym_base;
+ unsigned long reloc_size;
+ unsigned long text_size;
+ unsigned long text_start;
+ unsigned long data_size;
+ unsigned long data_start;
+ unsigned long bss_size;
+ PTR buff;
+ struct internal_filehdr internal_f;
+ struct internal_aouthdr internal_a;
+ int i;
+
+ bfd_error = system_call_error;
+
+ if(abfd->output_has_begun == false)
+ ecoff_compute_section_file_positions(abfd);
+
+ if (abfd->sections != (asection *) NULL)
+ scn_base = abfd->sections->filepos;
+ else
+ scn_base = 0;
+ reloc_base = ecoff_data (abfd)->reloc_filepos;
+
+ count = 1;
+ reloc_size = 0;
+ for (current = abfd->sections;
+ current != (asection *)NULL;
+ current = current->next)
+ {
+ if (strcmp (current->name, SCOMMON) == 0
+ || strcmp (current->name, REGINFO) == 0)
+ continue;
+ current->target_index = count;
+ ++count;
+ if (current->reloc_count != 0)
+ {
+ bfd_size_type relsize;
+
+ current->rel_filepos = reloc_base;
+ relsize = current->reloc_count * external_reloc_size;
+ reloc_size += relsize;
+ reloc_base += relsize;
+ }
+ else
+ current->rel_filepos = 0;
+ }
+
+ sym_base = reloc_base + reloc_size;
+
+ /* At least on Ultrix, the symbol table of an executable file must
+ be aligned to a page boundary. FIXME: Is this true on other
+ platforms? */
+ if ((abfd->flags & EXEC_P) != 0
+ && (abfd->flags & D_PAGED) != 0)
+ sym_base = (sym_base + round - 1) &~ (round - 1);
+
+ ecoff_data (abfd)->sym_filepos = sym_base;
+
+ if ((abfd->flags & D_PAGED) != 0)
+ text_size = ecoff_sizeof_headers (abfd, false);
+ else
+ text_size = 0;
+ text_start = 0;
+ data_size = 0;
+ data_start = 0;
+ bss_size = 0;
+
+ /* Write section headers to the file. */
+
+ buff = (PTR) alloca (scnhsz);
+ internal_f.f_nscns = 0;
+ if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0)
+ return false;
+ for (current = abfd->sections;
+ current != (asection *) NULL;
+ current = current->next)
+ {
+ struct internal_scnhdr section;
+ bfd_vma vma;
+
+ if (strcmp (current->name, SCOMMON) == 0)
+ {
+ BFD_ASSERT (bfd_get_section_size_before_reloc (current) == 0
+ && current->reloc_count == 0);
+ continue;
+ }
+ if (strcmp (current->name, REGINFO) == 0)
+ {
+ BFD_ASSERT (current->reloc_count == 0);
+ continue;
+ }
+
+ ++internal_f.f_nscns;
+
+ strncpy (section.s_name, current->name, sizeof section.s_name);
+
+ /* FIXME: is this correct for shared libraries? I think it is
+ but I have no platform to check. Ian Lance Taylor. */
+ vma = bfd_get_section_vma (abfd, current);
+ if (strcmp (current->name, _LIB) == 0)
+ section.s_vaddr = 0;
+ else
+ section.s_vaddr = vma;
+
+ section.s_paddr = vma;
+ section.s_size = bfd_get_section_size_before_reloc (current);
+
+ /* If this section is unloadable then the scnptr will be 0. */
+ if ((current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ section.s_scnptr = 0;
+ else
+ section.s_scnptr = current->filepos;
+ section.s_relptr = current->rel_filepos;
+
+ /* FIXME: the lnnoptr of the .sbss or .sdata section of an
+ object file produced by the assembler is supposed to point to
+ information about how much room is required by objects of
+ various different sizes. I think this only matters if we
+ want the linker to compute the best size to use, or
+ something. I don't know what happens if the information is
+ not present. */
+ section.s_lnnoptr = 0;
+
+ section.s_nreloc = current->reloc_count;
+ section.s_nlnno = 0;
+ section.s_flags = ecoff_sec_to_styp_flags (current->name,
+ current->flags);
+
+ bfd_coff_swap_scnhdr_out (abfd, (PTR) &section, buff);
+ if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
+ return false;
+
+ if ((section.s_flags & STYP_TEXT) != 0)
+ {
+ text_size += bfd_get_section_size_before_reloc (current);
+ if (text_start == 0 || text_start > vma)
+ text_start = vma;
+ }
+ else if ((section.s_flags & STYP_RDATA) != 0
+ || (section.s_flags & STYP_DATA) != 0
+ || (section.s_flags & STYP_LIT8) != 0
+ || (section.s_flags & STYP_LIT4) != 0
+ || (section.s_flags & STYP_SDATA) != 0)
+ {
+ data_size += bfd_get_section_size_before_reloc (current);
+ if (data_start == 0 || data_start > vma)
+ data_start = vma;
+ }
+ else if ((section.s_flags & STYP_BSS) != 0
+ || (section.s_flags & STYP_SBSS) != 0)
+ bss_size += bfd_get_section_size_before_reloc (current);
+ }
+
+ /* Set up the file header. */
+
+ internal_f.f_magic = ecoff_get_magic (abfd);
+
+ /* 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. */
+ internal_f.f_timdat = 0;
+
+ if (bfd_get_symcount (abfd) != 0)
+ {
+ /* The ECOFF f_nsyms field is not actually the number of
+ symbols, it's the size of symbolic information header. */
+ internal_f.f_nsyms = external_hdr_size;
+ internal_f.f_symptr = sym_base;
+ }
+ else
+ {
+ internal_f.f_nsyms = 0;
+ internal_f.f_symptr = 0;
+ }
+
+ internal_f.f_opthdr = aoutsz;
+
+ internal_f.f_flags = F_LNNO;
+ if (reloc_size == 0)
+ internal_f.f_flags |= F_RELFLG;
+ if (bfd_get_symcount (abfd) == 0)
+ internal_f.f_flags |= F_LSYMS;
+ if (abfd->flags & EXEC_P)
+ internal_f.f_flags |= F_EXEC;
+
+ if (! abfd->xvec->byteorder_big_p)
+ internal_f.f_flags |= F_AR32WR;
+ else
+ internal_f.f_flags |= F_AR32W;
+
+ /* Set up the ``optional'' header. */
+ if ((abfd->flags & D_PAGED) != 0)
+ internal_a.magic = ECOFF_AOUT_ZMAGIC;
+ else
+ internal_a.magic = ECOFF_AOUT_OMAGIC;
+
+ /* FIXME: This is what Ultrix puts in, and it makes the Ultrix
+ linker happy. But, is it right? */
+ internal_a.vstamp = 0x20a;
+
+ /* At least on Ultrix, these have to be rounded to page boundaries.
+ FIXME: Is this true on other platforms? */
+ if ((abfd->flags & D_PAGED) != 0)
+ {
+ internal_a.tsize = (text_size + round - 1) &~ (round - 1);
+ internal_a.text_start = text_start &~ (round - 1);
+ internal_a.dsize = (data_size + round - 1) &~ (round - 1);
+ internal_a.data_start = data_start &~ (round - 1);
+ }
+ else
+ {
+ internal_a.tsize = text_size;
+ internal_a.text_start = text_start;
+ internal_a.dsize = data_size;
+ internal_a.data_start = data_start;
+ }
+
+ /* On Ultrix, the initial portions of the .sbss and .bss segments
+ are at the end of the data section. The bsize field in the
+ optional header records how many bss bytes are required beyond
+ those in the data section. The value is not rounded to a page
+ boundary. */
+ if (bss_size < internal_a.dsize - data_size)
+ bss_size = 0;
+ else
+ bss_size -= internal_a.dsize - data_size;
+ internal_a.bsize = bss_size;
+ internal_a.bss_start = internal_a.data_start + internal_a.dsize;
+
+ internal_a.entry = bfd_get_start_address (abfd);
+
+ internal_a.gp_value = ecoff_data (abfd)->gp;
+
+ internal_a.gprmask = ecoff_data (abfd)->gprmask;
+ internal_a.fprmask = ecoff_data (abfd)->fprmask;
+ for (i = 0; i < 4; i++)
+ internal_a.cprmask[i] = ecoff_data (abfd)->cprmask[i];
+
+ /* Write out the file header and the optional header. */
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ return false;
+
+ buff = (PTR) alloca (filhsz);
+ bfd_coff_swap_filehdr_out (abfd, (PTR) &internal_f, buff);
+ if (bfd_write (buff, 1, filhsz, abfd) != filhsz)
+ return false;
+
+ buff = (PTR) alloca (aoutsz);
+ bfd_coff_swap_aouthdr_out (abfd, (PTR) &internal_a, buff);
+ if (bfd_write (buff, 1, aoutsz, abfd) != aoutsz)
+ return false;
+
+ /* Write out the relocs. */
+ for (current = abfd->sections;
+ current != (asection *) NULL;
+ current = current->next)
+ {
+ arelent **reloc_ptr_ptr;
+ arelent **reloc_end;
+ char *out_ptr;
+
+ if (current->reloc_count == 0)
+ continue;
+
+ buff = bfd_alloc (abfd, current->reloc_count * external_reloc_size);
+ if (buff == NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ reloc_ptr_ptr = current->orelocation;
+ reloc_end = reloc_ptr_ptr + current->reloc_count;
+ out_ptr = (char *) buff;
+ for (;
+ reloc_ptr_ptr < reloc_end;
+ reloc_ptr_ptr++, out_ptr += external_reloc_size)
+ {
+ arelent *reloc;
+ asymbol *sym;
+ struct internal_reloc in;
+
+ memset (&in, 0, sizeof in);
+
+ reloc = *reloc_ptr_ptr;
+ sym = *reloc->sym_ptr_ptr;
+
+ in.r_vaddr = reloc->address + bfd_get_section_vma (abfd, current);
+ in.r_type = reloc->howto->type;
+
+ if ((sym->flags & BSF_SECTION_SYM) == 0)
+ {
+ in.r_symndx = ecoff_get_sym_index (*reloc->sym_ptr_ptr);
+ in.r_extern = 1;
+ }
+ else
+ {
+ CONST char *name;
+
+ name = bfd_get_section_name (abfd, bfd_get_section (sym));
+ if (strcmp (name, ".text") == 0)
+ in.r_symndx = RELOC_SECTION_TEXT;
+ else if (strcmp (name, ".rdata") == 0)
+ in.r_symndx = RELOC_SECTION_RDATA;
+ else if (strcmp (name, ".data") == 0)
+ in.r_symndx = RELOC_SECTION_DATA;
+ else if (strcmp (name, ".sdata") == 0)
+ in.r_symndx = RELOC_SECTION_SDATA;
+ else if (strcmp (name, ".sbss") == 0)
+ in.r_symndx = RELOC_SECTION_SBSS;
+ else if (strcmp (name, ".bss") == 0)
+ in.r_symndx = RELOC_SECTION_BSS;
+ else if (strcmp (name, ".init") == 0)
+ in.r_symndx = RELOC_SECTION_INIT;
+ else if (strcmp (name, ".lit8") == 0)
+ in.r_symndx = RELOC_SECTION_LIT8;
+ else if (strcmp (name, ".lit4") == 0)
+ in.r_symndx = RELOC_SECTION_LIT4;
+ else
+ abort ();
+ in.r_extern = 0;
+ }
+
+ (*swap_reloc_out) (abfd, &in, (PTR) out_ptr);
+ }
+
+ if (bfd_seek (abfd, current->rel_filepos, SEEK_SET) != 0)
+ return false;
+ if (bfd_write (buff, external_reloc_size, current->reloc_count, abfd)
+ != external_reloc_size * current->reloc_count)
+ return false;
+ bfd_release (abfd, buff);
+ }
+
+ /* Write out the symbolic debugging information. */
+ if (bfd_get_symcount (abfd) > 0)
+ {
+ HDRR *symhdr;
+ unsigned long sym_offset;
+
+ /* Set up the offsets in the symbolic header. */
+ symhdr = &ecoff_data (abfd)->symbolic_header;
+ sym_offset = ecoff_data (abfd)->sym_filepos + external_hdr_size;
+
+#define SET(offset, size, ptr) \
+ if (symhdr->size == 0) \
+ symhdr->offset = 0; \
+ else \
+ symhdr->offset = (((char *) ecoff_data (abfd)->ptr \
+ - (char *) ecoff_data (abfd)->raw_syments) \
+ + sym_offset);
+
+ SET (cbLineOffset, cbLine, line);
+ SET (cbDnOffset, idnMax, external_dnr);
+ SET (cbPdOffset, ipdMax, external_pdr);
+ SET (cbSymOffset, isymMax, external_sym);
+ SET (cbOptOffset, ioptMax, external_opt);
+ SET (cbAuxOffset, iauxMax, external_aux);
+ SET (cbSsOffset, issMax, ss);
+ SET (cbSsExtOffset, issExtMax, ssext);
+ SET (cbFdOffset, ifdMax, external_fdr);
+ SET (cbRfdOffset, crfd, external_rfd);
+ SET (cbExtOffset, iextMax, external_ext);
+#undef SET
+
+ if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos,
+ SEEK_SET) != 0)
+ return false;
+ buff = (PTR) alloca (external_hdr_size);
+ (*backend->swap_hdr_out) (abfd, &ecoff_data (abfd)->symbolic_header,
+ buff);
+ if (bfd_write (buff, 1, external_hdr_size, abfd) != external_hdr_size)
+ return false;
+ if (bfd_write ((PTR) ecoff_data (abfd)->raw_syments, 1,
+ ecoff_data (abfd)->raw_size, abfd)
+ != ecoff_data (abfd)->raw_size)
+ return false;
+ }
+ else if ((abfd->flags & EXEC_P) != 0
+ && (abfd->flags & D_PAGED) != 0)
+ {
+ char c;
+
+ /* A demand paged executable must occupy an even number of
+ pages. */
+ if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
+ SEEK_SET) != 0)
+ return false;
+ if (bfd_read (&c, 1, 1, abfd) == 0)
+ c = 0;
+ if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
+ SEEK_SET) != 0)
+ return false;
+ if (bfd_write (&c, 1, 1, abfd) != 1)
+ return false;
+ }
+
+ return true;
+}
+
+/* Archive handling. ECOFF uses what appears to be a unique type of
+ archive header (which I call an armap). The byte ordering of the
+ armap and the contents are encoded in the name of the armap itself.
+ At least for now, we only support archives with the same byte
+ ordering in the armap and the contents.
+
+ The first four bytes in the armap are the number of symbol
+ definitions. This is always a power of two.
+
+ This is followed by the symbol definitions. Each symbol definition
+ occupies 8 bytes. The first four bytes are the offset from the
+ start of the armap strings to the null-terminated string naming
+ this symbol. The second four bytes are the file offset to the
+ archive member which defines this symbol. If the second four bytes
+ are 0, then this is not actually a symbol definition, and it should
+ be ignored.
+
+ The symbols are hashed into the armap with a closed hashing scheme.
+ See the functions below for the details of the algorithm.
+
+ We could use the hash table when looking up symbols in a library.
+ This would require a new BFD target entry point to replace the
+ bfd_get_next_mapent function used by the linker.
+
+ After the symbol definitions comes four bytes holding the size of
+ the string table, followed by the string table itself. */
+
+/* The name of an archive headers looks like this:
+ __________E[BL]E[BL]_ (with a trailing space).
+ The trailing space is changed to an X if the archive is changed to
+ indicate that the armap is out of date.
+
+ The Alpha seems to use ________64E[BL]E[BL]_. */
+
+#define ARMAP_BIG_ENDIAN 'B'
+#define ARMAP_LITTLE_ENDIAN 'L'
+#define ARMAP_MARKER 'E'
+#define ARMAP_START_LENGTH 10
+#define ARMAP_HEADER_MARKER_INDEX 10
+#define ARMAP_HEADER_ENDIAN_INDEX 11
+#define ARMAP_OBJECT_MARKER_INDEX 12
+#define ARMAP_OBJECT_ENDIAN_INDEX 13
+#define ARMAP_END_INDEX 14
+#define ARMAP_END "_ "
+
+/* This is a magic number used in the hashing algorithm. */
+#define ARMAP_HASH_MAGIC 0x9dd68ab5
+
+/* This returns the hash value to use for a string. It also sets
+ *REHASH to the rehash adjustment if the first slot is taken. SIZE
+ is the number of entries in the hash table, and HLOG is the log
+ base 2 of SIZE. */
+
+static unsigned int
+ecoff_armap_hash (s, rehash, size, hlog)
+ CONST char *s;
+ unsigned int *rehash;
+ unsigned int size;
+ unsigned int hlog;
+{
+ unsigned int hash;
+
+ hash = *s++;
+ while (*s != '\0')
+ hash = ((hash >> 27) | (hash << 5)) + *s++;
+ hash *= ARMAP_HASH_MAGIC;
+ *rehash = (hash & (size - 1)) | 1;
+ return hash >> (32 - hlog);
+}
+
+/* Read in the armap. */
+
+boolean
+ecoff_slurp_armap (abfd)
+ bfd *abfd;
+{
+ char nextname[17];
+ unsigned int i;
+ struct areltdata *mapdata;
+ bfd_size_type parsed_size;
+ char *raw_armap;
+ struct artdata *ardata;
+ unsigned int count;
+ char *raw_ptr;
+ struct symdef *symdef_ptr;
+ char *stringbase;
+
+ /* Get the name of the first element. */
+ i = bfd_read ((PTR) nextname, 1, 16, abfd);
+ if (i == 0)
+ return true;
+ if (i != 16)
+ return false;
+
+ bfd_seek (abfd, (file_ptr) -16, SEEK_CUR);
+
+ /* Irix 4.0.5F apparently can use either an ECOFF armap or a
+ standard COFF armap. We could move the ECOFF armap stuff into
+ bfd_slurp_armap, but that seems inappropriate since no other
+ target uses this format. Instead, we check directly for a COFF
+ armap. */
+ if (strncmp (nextname, "/ ", 16) == 0)
+ return bfd_slurp_armap (abfd);
+
+ /* See if the first element is an armap. */
+ if (strncmp (nextname, ecoff_backend (abfd)->armap_start,
+ ARMAP_START_LENGTH) != 0
+ || nextname[ARMAP_HEADER_MARKER_INDEX] != ARMAP_MARKER
+ || (nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN
+ && nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN)
+ || nextname[ARMAP_OBJECT_MARKER_INDEX] != ARMAP_MARKER
+ || (nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN
+ && nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN)
+ || strncmp (nextname + ARMAP_END_INDEX,
+ ARMAP_END, sizeof ARMAP_END - 1) != 0)
+ {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ /* Make sure we have the right byte ordering. */
+ if (((nextname[ARMAP_HEADER_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
+ ^ (abfd->xvec->header_byteorder_big_p != false))
+ || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
+ ^ (abfd->xvec->byteorder_big_p != false)))
+ {
+ bfd_error = wrong_format;
+ return false;
+ }
+
+ /* Read in the armap. */
+ ardata = bfd_ardata (abfd);
+ mapdata = snarf_ar_hdr (abfd);
+ if (mapdata == (struct areltdata *) NULL)
+ return false;
+ parsed_size = mapdata->parsed_size;
+ bfd_release (abfd, (PTR) mapdata);
+
+ raw_armap = (char *) bfd_alloc (abfd, parsed_size);
+ if (raw_armap == (char *) NULL)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+
+ if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size)
+ {
+ bfd_error = malformed_archive;
+ bfd_release (abfd, (PTR) raw_armap);
+ return false;
+ }
+
+ count = bfd_h_get_32 (abfd, (PTR) raw_armap);
+
+ ardata->symdef_count = 0;
+ ardata->cache = (struct ar_cache *) NULL;
+
+ /* This code used to overlay the symdefs over the raw archive data,
+ but that doesn't work on a 64 bit host. */
+
+ stringbase = raw_armap + count * 8 + 8;
+
+#ifdef CHECK_ARMAP_HASH
+ {
+ unsigned int hlog;
+
+ /* Double check that I have the hashing algorithm right by making
+ sure that every symbol can be looked up successfully. */
+ hlog = 0;
+ for (i = 1; i < count; i <<= 1)
+ hlog++;
+ BFD_ASSERT (i == count);
+
+ raw_ptr = raw_armap + 4;
+ for (i = 0; i < count; i++, raw_ptr += 8)
+ {
+ unsigned int name_offset, file_offset;
+ unsigned int hash, rehash, srch;
+
+ name_offset = bfd_h_get_32 (abfd, (PTR) raw_ptr);
+ file_offset = bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4));
+ if (file_offset == 0)
+ continue;
+ hash = ecoff_armap_hash (stringbase + name_offset, &rehash, count,
+ hlog);
+ if (hash == i)
+ continue;
+
+ /* See if we can rehash to this location. */
+ for (srch = (hash + rehash) & (count - 1);
+ srch != hash && srch != i;
+ srch = (srch + rehash) & (count - 1))
+ BFD_ASSERT (bfd_h_get_32 (abfd, (PTR) (raw_armap + 8 + srch * 8))
+ != 0);
+ BFD_ASSERT (srch == i);
+ }
+ }
+
+#endif /* CHECK_ARMAP_HASH */
+
+ raw_ptr = raw_armap + 4;
+ for (i = 0; i < count; i++, raw_ptr += 8)
+ if (bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4)) != 0)
+ ++ardata->symdef_count;
+
+ symdef_ptr = ((struct symdef *)
+ bfd_alloc (abfd,
+ ardata->symdef_count * sizeof (struct symdef)));
+ ardata->symdefs = (carsym *) symdef_ptr;
+
+ raw_ptr = raw_armap + 4;
+ for (i = 0; i < count; i++, raw_ptr += 8)
+ {
+ unsigned int name_offset, file_offset;
+
+ file_offset = bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4));
+ if (file_offset == 0)
+ continue;
+ name_offset = bfd_h_get_32 (abfd, (PTR) raw_ptr);
+ symdef_ptr->s.name = stringbase + name_offset;
+ symdef_ptr->file_offset = file_offset;
+ ++symdef_ptr;
+ }
+
+ ardata->first_file_filepos = bfd_tell (abfd);
+ /* Pad to an even boundary. */
+ ardata->first_file_filepos += ardata->first_file_filepos % 2;
+
+ bfd_has_map (abfd) = true;
+
+ return true;
+}
+
+/* Write out an armap. */
+
+boolean
+ecoff_write_armap (abfd, elength, map, orl_count, stridx)
+ bfd *abfd;
+ unsigned int elength;
+ struct orl *map;
+ unsigned int orl_count;
+ int stridx;
+{
+ unsigned int hashsize, hashlog;
+ unsigned int symdefsize;
+ int padit;
+ unsigned int stringsize;
+ unsigned int mapsize;
+ file_ptr firstreal;
+ struct ar_hdr hdr;
+ struct stat statbuf;
+ unsigned int i;
+ bfd_byte temp[4];
+ bfd_byte *hashtable;
+ bfd *current;
+ bfd *last_elt;
+
+ /* Ultrix appears to use as a hash table size the least power of two
+ greater than twice the number of entries. */
+ for (hashlog = 0; (1 << hashlog) <= 2 * orl_count; hashlog++)
+ ;
+ hashsize = 1 << hashlog;
+
+ symdefsize = hashsize * 8;
+ padit = stridx % 2;
+ stringsize = stridx + padit;
+
+ /* Include 8 bytes to store symdefsize and stringsize in output. */
+ mapsize = symdefsize + stringsize + 8;
+
+ firstreal = SARMAG + sizeof (struct ar_hdr) + mapsize + elength;
+
+ memset ((PTR) &hdr, 0, sizeof hdr);
+
+ /* Work out the ECOFF armap name. */
+ strcpy (hdr.ar_name, ecoff_backend (abfd)->armap_start);
+ hdr.ar_name[ARMAP_HEADER_MARKER_INDEX] = ARMAP_MARKER;
+ hdr.ar_name[ARMAP_HEADER_ENDIAN_INDEX] =
+ (abfd->xvec->header_byteorder_big_p
+ ? ARMAP_BIG_ENDIAN
+ : ARMAP_LITTLE_ENDIAN);
+ hdr.ar_name[ARMAP_OBJECT_MARKER_INDEX] = ARMAP_MARKER;
+ hdr.ar_name[ARMAP_OBJECT_ENDIAN_INDEX] =
+ abfd->xvec->byteorder_big_p ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN;
+ memcpy (hdr.ar_name + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1);
+
+ /* Write the timestamp of the archive header to be just a little bit
+ later than the timestamp of the file, otherwise the linker will
+ complain that the index is out of date. Actually, the Ultrix
+ linker just checks the archive name; the GNU linker may check the
+ date. */
+ stat (abfd->filename, &statbuf);
+ sprintf (hdr.ar_date, "%ld", (long) (statbuf.st_mtime + 60));
+
+ /* The DECstation uses zeroes for the uid, gid and mode of the
+ armap. */
+ hdr.ar_uid[0] = '0';
+ hdr.ar_gid[0] = '0';
+ hdr.ar_mode[0] = '0';
+
+ sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+
+ hdr.ar_fmag[0] = '`';
+ hdr.ar_fmag[1] = '\n';
+
+ /* Turn all null bytes in the header into spaces. */
+ for (i = 0; i < sizeof (struct ar_hdr); i++)
+ if (((char *)(&hdr))[i] == '\0')
+ (((char *)(&hdr))[i]) = ' ';
+
+ if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
+ != sizeof (struct ar_hdr))
+ return false;
+
+ bfd_h_put_32 (abfd, hashsize, temp);
+ if (bfd_write (temp, 1, 4, abfd) != 4)
+ return false;
+
+ hashtable = (bfd_byte *) bfd_zalloc (abfd, symdefsize);
+
+ current = abfd->archive_head;
+ last_elt = current;
+ for (i = 0; i < orl_count; i++)
+ {
+ unsigned int hash, rehash;
+
+ /* Advance firstreal to the file position of this archive
+ element. */
+ if (((bfd *) map[i].pos) != last_elt)
+ {
+ do
+ {
+ firstreal += arelt_size (current) + sizeof (struct ar_hdr);
+ firstreal += firstreal % 2;
+ current = current->next;
+ }
+ while (current != (bfd *) map[i].pos);
+ }
+
+ last_elt = current;
+
+ hash = ecoff_armap_hash (*map[i].name, &rehash, hashsize, hashlog);
+ if (bfd_h_get_32 (abfd, (PTR) (hashtable + (hash * 8) + 4)) != 0)
+ {
+ unsigned int srch;
+
+ /* The desired slot is already taken. */
+ for (srch = (hash + rehash) & (hashsize - 1);
+ srch != hash;
+ srch = (srch + rehash) & (hashsize - 1))
+ if (bfd_h_get_32 (abfd, (PTR) (hashtable + (srch * 8) + 4)) == 0)
+ break;
+
+ BFD_ASSERT (srch != hash);
+
+ hash = srch;
+ }
+
+ bfd_h_put_32 (abfd, map[i].namidx, (PTR) (hashtable + hash * 8));
+ bfd_h_put_32 (abfd, firstreal, (PTR) (hashtable + hash * 8 + 4));
+ }
+
+ if (bfd_write (hashtable, 1, symdefsize, abfd) != symdefsize)
+ return false;
+
+ bfd_release (abfd, hashtable);
+
+ /* Now write the strings. */
+ bfd_h_put_32 (abfd, stringsize, temp);
+ if (bfd_write (temp, 1, 4, abfd) != 4)
+ return false;
+ for (i = 0; i < orl_count; i++)
+ {
+ bfd_size_type len;
+
+ len = strlen (*map[i].name) + 1;
+ if (bfd_write ((PTR) (*map[i].name), 1, len, abfd) != len)
+ return false;
+ }
+
+ /* The spec sez this should be a newline. But in order to be
+ bug-compatible for DECstation ar we use a null. */
+ if (padit)
+ {
+ if (bfd_write ("\0", 1, 1, abfd) != 1)
+ return false;
+ }
+
+ return true;
+}
+
+/* See whether this BFD is an archive. If it is, read in the armap
+ and the extended name table. */
+
+bfd_target *
+ecoff_archive_p (abfd)
+ bfd *abfd;
+{
+ char armag[SARMAG + 1];
+
+ if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG
+ || strncmp (armag, ARMAG, SARMAG) != 0)
+ {
+ bfd_error = wrong_format;
+ return (bfd_target *) NULL;
+ }
+
+ /* We are setting bfd_ardata(abfd) here, but since bfd_ardata
+ involves a cast, we can't do it as the left operand of
+ assignment. */
+ abfd->tdata.aout_ar_data =
+ (struct artdata *) bfd_zalloc (abfd, sizeof (struct artdata));
+
+ if (bfd_ardata (abfd) == (struct artdata *) NULL)
+ {
+ bfd_error = no_memory;
+ return (bfd_target *) NULL;
+ }
+
+ bfd_ardata (abfd)->first_file_filepos = SARMAG;
+
+ if (ecoff_slurp_armap (abfd) == false
+ || ecoff_slurp_extended_name_table (abfd) == false)
+ {
+ bfd_release (abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = (struct artdata *) NULL;
+ return (bfd_target *) NULL;
+ }
+
+ return abfd->xvec;
+}
diff --git a/gnu/usr.bin/gdb/bfd/elf.c b/gnu/usr.bin/gdb/bfd/elf.c
new file mode 100644
index 000000000000..2fcf2f143439
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/elf.c
@@ -0,0 +1,248 @@
+/* ELF executable support for BFD.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+
+SECTION
+ ELF backends
+
+ BFD support for ELF formats is being worked on.
+ Currently, the best supported back ends are for sparc and i386
+ (running svr4 or Solaris 2).
+
+ Documentation of the internals of the support code still needs
+ to be written. The code is changing quickly enough that we
+ haven't bothered yet.
+ */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#define ARCH_SIZE 0
+#include "libelf.h"
+
+/* Standard ELF hash function. Do not change this function; you will
+ cause invalid hash tables to be generated. (Well, you would if this
+ were being used yet.) */
+unsigned long
+DEFUN (bfd_elf_hash, (name),
+ CONST unsigned char *name)
+{
+ unsigned long h = 0;
+ unsigned long g;
+ int ch;
+
+ while ((ch = *name++) != '\0')
+ {
+ h = (h << 4) + ch;
+ if ((g = (h & 0xf0000000)) != 0)
+ {
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ }
+ return h;
+}
+
+/* Read a specified number of bytes at a specified offset in an ELF
+ file, into a newly allocated buffer, and return a pointer to the
+ buffer. */
+
+static char *
+DEFUN (elf_read, (abfd, offset, size),
+ bfd * abfd AND
+ long offset AND
+ int size)
+{
+ char *buf;
+
+ if ((buf = bfd_alloc (abfd, size)) == NULL)
+ {
+ bfd_error = no_memory;
+ return NULL;
+ }
+ if (bfd_seek (abfd, offset, SEEK_SET) == -1)
+ {
+ bfd_error = system_call_error;
+ return NULL;
+ }
+ if (bfd_read ((PTR) buf, size, 1, abfd) != size)
+ {
+ bfd_error = system_call_error;
+ return NULL;
+ }
+ return buf;
+}
+
+boolean
+DEFUN (elf_mkobject, (abfd), bfd * abfd)
+{
+ /* this just does initialization */
+ /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */
+ elf_tdata (abfd) = (struct elf_obj_tdata *)
+ bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
+ if (elf_tdata (abfd) == 0)
+ {
+ bfd_error = no_memory;
+ return false;
+ }
+ /* since everything is done at close time, do we need any
+ initialization? */
+
+ return true;
+}
+
+char *
+DEFUN (elf_get_str_section, (abfd, shindex),
+ bfd * abfd AND
+ unsigned int shindex)
+{
+ Elf_Internal_Shdr **i_shdrp;
+ char *shstrtab = NULL;
+ unsigned int offset;
+ unsigned int shstrtabsize;
+
+ i_shdrp = elf_elfsections (abfd);
+ if (i_shdrp == 0 || i_shdrp[shindex] == 0)
+ return 0;
+
+ shstrtab = i_shdrp[shindex]->rawdata;
+ if (shstrtab == NULL)
+ {
+ /* No cached one, attempt to read, and cache what we read. */
+ offset = i_shdrp[shindex]->sh_offset;
+ shstrtabsize = i_shdrp[shindex]->sh_size;
+ shstrtab = elf_read (abfd, offset, shstrtabsize);
+ i_shdrp[shindex]->rawdata = (void *) shstrtab;
+ }
+ return shstrtab;
+}
+
+char *
+DEFUN (elf_string_from_elf_section, (abfd, shindex, strindex),
+ bfd * abfd AND
+ unsigned int shindex AND
+ unsigned int strindex)
+{
+ Elf_Internal_Shdr *hdr;
+
+ if (strindex == 0)
+ return "";
+
+ hdr = elf_elfsections (abfd)[shindex];
+
+ if (!hdr->rawdata
+ && elf_get_str_section (abfd, shindex) == NULL)
+ return NULL;
+
+ return ((char *) hdr->rawdata) + strindex;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_elf_find_section
+
+SYNOPSIS
+ struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name);
+
+DESCRIPTION
+ Helper functions for GDB to locate the string tables.
+ Since BFD hides string tables from callers, GDB needs to use an
+ internal hook to find them. Sun's .stabstr, in particular,
+ isn't even pointed to by the .stab section, so ordinary
+ mechanisms wouldn't work to find it, even if we had some.
+*/
+
+struct elf_internal_shdr *
+DEFUN (bfd_elf_find_section, (abfd, name),
+ bfd * abfd AND
+ char *name)
+{
+ Elf_Internal_Shdr **i_shdrp;
+ char *shstrtab;
+ unsigned int max;
+ unsigned int i;
+
+ i_shdrp = elf_elfsections (abfd);
+ if (i_shdrp != NULL)
+ {
+ shstrtab = elf_get_str_section (abfd, elf_elfheader (abfd)->e_shstrndx);
+ if (shstrtab != NULL)
+ {
+ max = elf_elfheader (abfd)->e_shnum;
+ for (i = 1; i < max; i++)
+ if (!strcmp (&shstrtab[i_shdrp[i]->sh_name], name))
+ return i_shdrp[i];
+ }
+ }
+ return 0;
+}
+
+const struct bfd_elf_arch_map bfd_elf_arch_map[] = {
+ { bfd_arch_sparc, EM_SPARC },
+ { bfd_arch_i386, EM_386 },
+ { bfd_arch_m68k, EM_68K },
+ { bfd_arch_m88k, EM_88K },
+ { bfd_arch_i860, EM_860 },
+ { bfd_arch_mips, EM_MIPS },
+ { bfd_arch_hppa, EM_HPPA },
+};
+
+const int bfd_elf_arch_map_size = sizeof (bfd_elf_arch_map) / sizeof (bfd_elf_arch_map[0]);
+
+const char *const bfd_elf_section_type_names[] = {
+ "SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB",
+ "SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE",
+ "SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
+};
+
+/* ELF relocs are against symbols. If we are producing relocateable
+ output, and the reloc is against an external symbol, and nothing
+ has given us any additional addend, the resulting reloc will also
+ be against the same symbol. In such a case, we don't want to
+ change anything about the way the reloc is handled, since it will
+ all be done at final link time. Rather than put special case code
+ into bfd_perform_relocation, all the reloc types use this howto
+ function. It just short circuits the reloc if producing
+ relocateable output against an external symbol. */
+
+bfd_reloc_status_type
+bfd_elf_generic_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+{
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ return bfd_reloc_continue;
+}
diff --git a/gnu/usr.bin/gdb/bfd/format.c b/gnu/usr.bin/gdb/bfd/format.c
new file mode 100644
index 000000000000..6a80ed7082ae
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/format.c
@@ -0,0 +1,258 @@
+/* Generic BFD support for file formats.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ File Formats
+
+ A format is a BFD concept of high level file contents. The
+ formats supported by BFD are:
+
+ o bfd_object
+
+ The BFD may contain data, symbols, relocations and debug info.
+
+ o bfd_archive
+
+ The BFD contains other BFDs and an optional index.
+
+ o bfd_core
+
+ The BFD contains the result of an executable core dump.
+
+
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+extern bfd_target *target_vector[];
+extern bfd_target *default_vector[];
+
+
+/*
+FUNCTION
+ bfd_check_format
+
+SYNOPSIS
+ boolean bfd_check_format(bfd *abfd, bfd_format format);
+
+DESCRIPTION
+ This routine is supplied a BFD and a format. It attempts to
+ verify if the file attached to the BFD is indeed compatible
+ with the format specified (ie, one of <<bfd_object>>,
+ <<bfd_archive>> or <<bfd_core>>).
+
+ If the BFD has been set to a specific @var{target} before the
+ call, only the named target and format combination will be
+ checked. If the target has not been set, or has been set to
+ <<default>> then all the known target backends will be
+ interrogated to determine a match. If the default target
+ matches, it is used. If not, exactly one target must recognize
+ the file, or an error results.
+
+ The function returns <<true>> on success, otherwise <<false>>
+ with one of the following error codes:
+
+ o invalid_operation -
+ if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or
+ <<bfd_core>>.
+
+ o system_call_error -
+ if an error occured during a read - even some file mismatches
+ can cause system_call_errors
+
+ o file_not_recognised -
+ none of the backends recognised the file format
+
+ o file_ambiguously_recognized -
+ more than one backend recognised the file format.
+
+*/
+
+boolean
+DEFUN(bfd_check_format,(abfd, format),
+ bfd *abfd AND
+ bfd_format format)
+{
+ 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;
+
+
+ /* Since the target type was defaulted, check them
+ all in the hope that one will be uniquely recognized. */
+
+ save_targ = abfd->xvec;
+ match_count = 0;
+ right_targ = 0;
+
+
+ /* presume the answer is yes */
+ abfd->format = format;
+
+ /* If the target type was explicitly specified, just check that target. */
+
+ if (!abfd->target_defaulted) {
+ bfd_seek (abfd, (file_ptr)0, SEEK_SET); /* 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 */
+ }
+ }
+
+ for (target = target_vector; *target != NULL; target++) {
+ bfd_target *temp;
+
+ abfd->xvec = *target; /* Change BFD's target temporarily */
+ bfd_seek (abfd, (file_ptr)0, SEEK_SET);
+ /* If _bfd_check_format neglects to set bfd_error, assume wrong_format.
+ We didn't used to even pay any attention to bfd_error, so I suspect
+ that some _bfd_check_format might have this problem. */
+ bfd_error = wrong_format;
+ temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
+ if (temp) { /* This format checks out as ok! */
+ right_targ = temp;
+ match_count++;
+ /* If this is the default target, accept it, even if other targets
+ might match. People who want those other targets have to set
+ the GNUTARGET variable. */
+ if (temp == default_vector[0])
+ {
+ match_count = 1;
+ break;
+ }
+#ifdef GNU960
+ /* Big- and little-endian b.out archives look the same, but it doesn't
+ * matter: there is no difference in their headers, and member file byte
+ * orders will (I hope) be handled appropriately by bfd. Ditto for big
+ * and little coff archives. And the 4 coff/b.out object formats are
+ * unambiguous. So accept the first match we find.
+ */
+ break;
+#endif
+ } else if (bfd_error != wrong_format) {
+ abfd->xvec = save_targ;
+ abfd->format = bfd_unknown;
+ return false;
+ }
+ }
+
+ 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);
+ return false;
+}
+
+
+/*
+FUNCTION
+ bfd_set_format
+
+SYNOPSIS
+ boolean bfd_set_format(bfd *, bfd_format);
+
+DESCRIPTION
+ This function sets the file format of the supplied BFD to the
+ format requested. If the target set in the BFD does not
+ support the format requested, the format is illegal or the BFD
+ is not open for writing than an error occurs.
+
+*/
+
+boolean
+DEFUN(bfd_set_format,(abfd, format),
+ bfd *abfd AND
+ bfd_format format)
+{
+
+ 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 (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) {
+ abfd->format = bfd_unknown;
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+FUNCTION
+ bfd_format_string
+
+SYNOPSIS
+ CONST char *bfd_format_string(bfd_format);
+
+DESCRIPTION
+ This function takes one argument, and enumerated type
+ (bfd_format) and returns a pointer to a const string
+ <<invalid>>, <<object>>, <<archive>>, <<core>> or <<unknown>>
+ depending upon the value of the enumeration.
+*/
+
+CONST char *
+DEFUN(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";
+ }
+}
diff --git a/gnu/usr.bin/gdb/bfd/freebsd386.c b/gnu/usr.bin/gdb/bfd/freebsd386.c
new file mode 100644
index 000000000000..22cbd6ad1701
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/freebsd386.c
@@ -0,0 +1,110 @@
+/* BFD back-end for i386 a.out binaries under BSD.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This data should be correct for the format used under all the various
+ BSD ports for 386 machines. */
+
+#define BYTES_IN_WORD 4
+#define ARCH 32
+
+/* ZMAGIC files never have the header in the text. */
+#define N_HEADER_IN_TEXT(x) 0
+
+/* ZMAGIC files start at address 0. This does not apply to QMAGIC. */
+#define TEXT_START_ADDR 0
+
+#define SEGMENT_SIZE PAGE_SIZE
+
+#define DEFAULT_ARCH bfd_arch_i386
+#define MACHTYPE_OK(mtype) ((mtype) == M_386 || (mtype) == M_386_NETBSD || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(freebsd386_,OP)
+#define TARGETNAME "a.out-freebsd-386"
+
+#define N_MAGIC(ex) \
+ ((ex).a_info & 0xffff)
+#define N_MACHTYPE(ex) \
+ ( (N_GETMAGIC_NET(ex) == ZMAGIC) ? N_GETMID_NET(ex) : \
+ ((ex).a_info >> 16) & 0x03ff )
+#define N_FLAGS(ex) \
+ ( (N_GETMAGIC_NET(ex) == ZMAGIC) ? N_GETFLAG_NET(ex) : \
+ ((ex).a_info >> 26) & 0x3f )
+#define N_SET_INFO(ex,mag,mid,flag) \
+ ( (ex).a_info = (((flag) & 0x3f) <<26) | (((mid) & 0x03ff) << 16) | \
+ ((mag) & 0xffff) )
+
+#define N_GETMAGIC_NET(ex) \
+ (ntohl((ex).a_info) & 0xffff)
+#define N_GETMID_NET(ex) \
+ ((ntohl((ex).a_info) >> 16) & 0x03ff)
+#define N_GETFLAG_NET(ex) \
+ ((ntohl((ex).a_info) >> 26) & 0x3f)
+#define N_SETMAGIC_NET(ex,mag,mid,flag) \
+ ( (ex).a_info = htonl( (((flag)&0x3f)<<26) | (((mid)&0x03ff)<<16) | \
+ (((mag)&0xffff)) ) )
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+#define N_ALIGN(ex,x) \
+ (N_MAGIC(ex) == ZMAGIC || N_MAGIC(ex) == QMAGIC || \
+ N_GETMAGIC_NET(ex) == ZMAGIC || N_GETMAGIC_NET(ex) == QMAGIC ? \
+ ((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1) : (x))
+
+/* Valid magic number check. */
+#define N_BADMAG(ex) \
+ (N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != NMAGIC && \
+ N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC && \
+ N_GETMAGIC_NET(ex) != OMAGIC && N_GETMAGIC_NET(ex) != NMAGIC && \
+ N_GETMAGIC_NET(ex) != ZMAGIC && N_GETMAGIC_NET(ex) != QMAGIC)
+
+/* Address of the bottom of the text segment. */
+#define N_TXTADDR(ex) \
+ ((N_MAGIC(ex) == OMAGIC || N_MAGIC(ex) == NMAGIC || \
+ N_MAGIC(ex) == ZMAGIC) ? 0 : PAGE_SIZE)
+
+/* Address of the bottom of the data segment. */
+#define N_DATADDR(ex) \
+ N_ALIGN(ex, N_TXTADDR(ex) + (ex).a_text)
+
+/* Text segment offset. */
+#define N_TXTOFF(ex) \
+ (N_MAGIC(ex) == ZMAGIC ? PAGE_SIZE : (N_MAGIC(ex) == QMAGIC || \
+ N_GETMAGIC_NET(ex) == ZMAGIC) ? 0 : EXEC_BYTES_SIZE)
+
+/* Data segment offset. */
+#define N_DATOFF(ex) \
+ N_ALIGN(ex, N_TXTOFF(ex) + (ex).a_text)
+
+/* Relocation table offset. */
+#define N_RELOFF(ex) \
+ N_ALIGN(ex, N_DATOFF(ex) + (ex).a_data)
+
+/* Symbol table offset. */
+#define N_SYMOFF(ex) \
+ (N_RELOFF(ex) + (ex).a_trsize + (ex).a_drsize)
+
+/* String table offset. */
+#define N_STROFF(ex) (N_SYMOFF(ex) + (ex).a_syms)
+
+#define NO_SWAP_MAGIC /* magic number already in correct endian format */
+
+#include "aout-target.h"
diff --git a/gnu/usr.bin/gdb/bfd/init.c b/gnu/usr.bin/gdb/bfd/init.c
new file mode 100644
index 000000000000..30a275935c10
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/init.c
@@ -0,0 +1,78 @@
+/* bfd initialization stuff
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Written by Steve Chamberlain of Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+extern void DEFUN_VOID (bfd_section_init);
+
+static boolean initialized = false;
+
+/*
+SECTION
+ Initialization
+
+ This is the initialization section
+
+*/
+
+/*
+FUNCTION
+ bfd_init
+
+SYNOPSIS
+ void bfd_init(void);
+
+DESCRIPTION
+ This routine must be called before any other bfd function to
+ initialize magical internal data structures.
+*/
+
+void DEFUN_VOID(bfd_init)
+{
+ if (initialized == false) {
+ initialized = true;
+
+ bfd_arch_init();
+ }
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_check_init
+
+DESCRIPTION
+ This routine is called before any other bfd function using
+ initialized data is used to ensure that the structures have
+ been initialized. Soon this function will go away, and the bfd
+ library will assume that bfd_init has been called.
+
+SYNOPSIS
+ void bfd_check_init(void);
+*/
+
+void DEFUN_VOID(bfd_check_init)
+{
+ if (initialized == false) {
+ bfd_init();
+ }
+}
diff --git a/gnu/usr.bin/gdb/bfd/libaout.h b/gnu/usr.bin/gdb/bfd/libaout.h
new file mode 100644
index 000000000000..0d99d0c43dba
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/libaout.h
@@ -0,0 +1,393 @@
+/* BFD back-end data structures for a.out (and similar) files.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* We try to encapsulate the differences in the various a.out file
+ variants 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. */
+
+/* Parameterize the a.out code based on whether it is being built
+ for a 32-bit architecture or a 64-bit architecture. */
+#if ARCH_SIZE==64
+#define GET_WORD bfd_h_get_64
+#define GET_SWORD bfd_h_get_signed_64
+#define PUT_WORD bfd_h_put_64
+#ifndef NAME
+#define NAME(x,y) CAT3(x,_64_,y)
+#endif
+#define JNAME(x) CAT(x,_64)
+#define BYTES_IN_WORD 8
+#else /* ARCH_SIZE == 32 */
+#define GET_WORD bfd_h_get_32
+#define GET_SWORD bfd_h_get_signed_32
+#define PUT_WORD bfd_h_put_32
+#ifndef NAME
+#define NAME(x,y) CAT3(x,_32_,y)
+#endif
+#define JNAME(x) CAT(x,_32)
+#define BYTES_IN_WORD 4
+#endif /* ARCH_SIZE==32 */
+
+/* Declare these types at file level, since they are used in parameter
+ lists, which have wierd scope. */
+struct external_exec;
+struct internal_exec;
+
+/* Back-end information for various a.out targets. */
+struct aout_backend_data
+{
+ /* Are ZMAGIC files mapped contiguously? If so, the text section may
+ need more padding, if the segment size (granularity for memory access
+ control) is larger than the page size. */
+ unsigned char zmagic_mapped_contiguous;
+ /* If this flag is set, ZMAGIC/NMAGIC file headers get mapped in with the
+ text section, which starts immediately after the file header.
+ If not, the text section starts on the next page. */
+ unsigned char text_includes_header;
+
+ /* If the text section VMA isn't specified, and we need an absolute
+ address, use this as the default. If we're producing a relocatable
+ file, zero is always used. */
+ /* ?? Perhaps a callback would be a better choice? Will this do anything
+ reasonable for a format that handles multiple CPUs with different
+ load addresses for each? */
+ bfd_vma default_text_vma;
+
+ /* Callback for setting the page and segment sizes, if they can't be
+ trivially determined from the architecture. */
+ boolean (*set_sizes) PARAMS ((bfd *));
+
+ /* zmagic files only. For go32, the length of the exec header contributes
+ to the size of the text section in the file for alignment purposes but
+ does *not* get counted in the length of the text section. */
+ unsigned char exec_header_not_counted;
+};
+#define aout_backend_info(abfd) \
+ ((CONST struct aout_backend_data *)((abfd)->xvec->backend_data))
+
+/* This is the layout in memory of a "struct exec" while we process it.
+ All 'lengths' are given as a number of bytes.
+ All 'alignments' are for relinkable files only; an alignment of
+ 'n' indicates the corresponding segment must begin at an
+ address that is a multiple of (2**n). */
+
+struct internal_exec
+{
+ long a_info; /* Magic number and flags, packed */
+ bfd_vma a_text; /* length of text, in bytes */
+ bfd_vma a_data; /* length of data, in bytes */
+ bfd_vma a_bss; /* length of uninitialized data area in mem */
+ bfd_vma a_syms; /* length of symbol table data in file */
+ bfd_vma a_entry; /* start address */
+ bfd_vma a_trsize; /* length of text's relocation info, in bytes */
+ bfd_vma a_drsize; /* length of data's relocation info, in bytes */
+ /* Added for i960 */
+ bfd_vma a_tload; /* Text runtime load address */
+ bfd_vma a_dload; /* Data runtime load address */
+ unsigned char a_talign; /* Alignment of text segment */
+ unsigned char a_dalign; /* Alignment of data segment */
+ unsigned char a_balign; /* Alignment of bss segment */
+ char a_relaxable; /* Enough info for linker relax */
+};
+
+/* Magic number is written
+< MSB >
+3130292827262524232221201918171615141312111009080706050403020100
+< FLAGS >< MACHINE TYPE >< MAGIC NUMBER >
+*/
+/* Magic number for NetBSD is
+<MSB >
+3130292827262524232221201918171615141312111009080706050403020100
+< FLAGS >< >< MAGIC NUMBER >
+*/
+
+enum machine_type {
+ M_UNKNOWN = 0,
+ M_68010 = 1,
+ M_68020 = 2,
+ M_SPARC = 3,
+ /* skip a bunch so we don't run into any of suns numbers */
+ M_386 = 100,
+ M_29K = 101, /* AMD 29000 */
+ M_386_DYNIX = 102, /* Sequent running dynix */
+ M_386_NETBSD = 134, /* NetBSD/386 binary */
+ M_MIPS1 = 151, /* MIPS R2000/R3000 binary */
+ M_MIPS2 = 152, /* MIPS R4000/R6000 binary */
+ M_HP200 = 200, /* HP 200 (68010) BSD binary */
+ M_HP300 = (300 % 256), /* HP 300 (68020+68881) BSD binary */
+ M_HPUX = (0x20c % 256)/* HP 200/300 HPUX binary */
+};
+
+#define N_DYNAMIC(exec) ((exec).a_info & 0x8000000)
+
+#ifndef N_MAGIC
+# define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#endif
+
+#ifndef N_MACHTYPE
+# define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#endif
+
+#ifndef N_FLAGS
+# define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#endif
+
+#ifndef N_SET_INFO
+# define N_SET_INFO(exec, magic, type, flags) \
+((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((flags) & 0xff) << 24))
+#endif
+
+#ifndef N_SET_MAGIC
+# define N_SET_MAGIC(exec, magic) \
+((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
+#endif
+
+#ifndef N_SET_MACHTYPE
+# define N_SET_MACHTYPE(exec, machtype) \
+((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+#endif
+
+#ifndef N_SET_FLAGS
+# define N_SET_FLAGS(exec, flags) \
+((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+#endif
+
+typedef struct aout_symbol {
+ asymbol symbol;
+ short desc;
+ char other;
+ unsigned char type;
+} aout_symbol_type;
+
+/* The `tdata' struct for all a.out-like object file formats.
+ Various things depend on this struct being around any time an a.out
+ file is being handled. An example is dbxread.c in GDB. */
+
+struct aoutdata {
+ struct internal_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;
+
+ /* Size of a relocation entry in external form */
+ unsigned reloc_entry_size;
+
+ /* Size of a symbol table entry in external form */
+ unsigned symbol_entry_size;
+
+ /* Page size - needed for alignment of demand paged files. */
+ unsigned long page_size;
+
+ /* Segment size - needed for alignment of demand paged files. */
+ unsigned long segment_size;
+
+ unsigned exec_bytes_size;
+ unsigned vma_adjusted : 1;
+
+ /* used when a bfd supports several highly similar formats */
+ enum {
+ default_format = 0,
+ gnu_encap_format } subformat;
+
+ enum {
+ undecided_magic = 0,
+ z_magic,
+ o_magic,
+ n_magic } magic;
+};
+
+struct aout_data_struct {
+ struct aoutdata a;
+ struct internal_exec e;
+};
+
+#define adata(bfd) ((bfd)->tdata.aout_data->a)
+#define exec_hdr(bfd) (adata(bfd).hdr)
+#define obj_aout_symbols(bfd) (adata(bfd).symbols)
+#define obj_textsec(bfd) (adata(bfd).textsec)
+#define obj_datasec(bfd) (adata(bfd).datasec)
+#define obj_bsssec(bfd) (adata(bfd).bsssec)
+#define obj_sym_filepos(bfd) (adata(bfd).sym_filepos)
+#define obj_str_filepos(bfd) (adata(bfd).str_filepos)
+#define obj_reloc_entry_size(bfd) (adata(bfd).reloc_entry_size)
+#define obj_symbol_entry_size(bfd) (adata(bfd).symbol_entry_size)
+#define obj_aout_subformat(bfd) (adata(bfd).subformat)
+
+/* We take the address of the first element of an asymbol to ensure that the
+ macro is only ever applied to an asymbol */
+#define aout_symbol(asymbol) ((aout_symbol_type *)(&(asymbol)->the_bfd))
+
+/* Prototype declarations for functions defined in aoutx.h */
+
+boolean
+NAME(aout,squirt_out_relocs) PARAMS ((bfd *abfd, asection *section));
+
+bfd_target *
+NAME(aout,some_aout_object_p) PARAMS ((bfd *abfd,
+ struct internal_exec *execp,
+ bfd_target * (*callback)(bfd *)));
+
+boolean
+NAME(aout,mkobject) PARAMS ((bfd *abfd));
+
+enum machine_type
+NAME(aout,machine_type) PARAMS ((enum bfd_architecture arch,
+ unsigned long machine));
+
+boolean
+NAME(aout,set_arch_mach) PARAMS ((bfd *abfd, enum bfd_architecture arch,
+ unsigned long machine));
+
+boolean
+NAME(aout,new_section_hook) PARAMS ((bfd *abfd, asection *newsect));
+
+boolean
+NAME(aout,set_section_contents) PARAMS ((bfd *abfd, sec_ptr section,
+ PTR location, file_ptr offset, bfd_size_type count));
+
+asymbol *
+NAME(aout,make_empty_symbol) PARAMS ((bfd *abfd));
+
+boolean
+NAME(aout,slurp_symbol_table) PARAMS ((bfd *abfd));
+
+void
+NAME(aout,write_syms) PARAMS ((bfd *abfd));
+
+void
+NAME(aout,reclaim_symbol_table) PARAMS ((bfd *abfd));
+
+unsigned int
+NAME(aout,get_symtab_upper_bound) PARAMS ((bfd *abfd));
+
+unsigned int
+NAME(aout,get_symtab) PARAMS ((bfd *abfd, asymbol **location));
+
+boolean
+NAME(aout,slurp_reloc_table) PARAMS ((bfd *abfd, sec_ptr asect,
+ asymbol **symbols));
+
+unsigned int
+NAME(aout,canonicalize_reloc) PARAMS ((bfd *abfd, sec_ptr section,
+ arelent **relptr, asymbol **symbols));
+
+unsigned int
+NAME(aout,get_reloc_upper_bound) PARAMS ((bfd *abfd, sec_ptr asect));
+
+void
+NAME(aout,reclaim_reloc) PARAMS ((bfd *ignore_abfd, sec_ptr ignore));
+
+alent *
+NAME(aout,get_lineno) PARAMS ((bfd *ignore_abfd, asymbol *ignore_symbol));
+
+void
+NAME(aout,print_symbol) PARAMS ((bfd *ignore_abfd, PTR file,
+ asymbol *symbol, bfd_print_symbol_type how));
+
+void
+NAME(aout,get_symbol_info) PARAMS ((bfd *ignore_abfd,
+ asymbol *symbol, symbol_info *ret));
+
+boolean
+NAME(aout,close_and_cleanup) PARAMS ((bfd *abfd));
+
+boolean
+NAME(aout,find_nearest_line) PARAMS ((bfd *abfd, asection *section,
+ asymbol **symbols, bfd_vma offset, CONST char **filename_ptr,
+ CONST char **functionname_ptr, unsigned int *line_ptr));
+
+int
+NAME(aout,sizeof_headers) PARAMS ((bfd *abfd, boolean exec));
+
+boolean
+NAME(aout,adjust_sizes_and_vmas) PARAMS ((bfd *abfd,
+ bfd_size_type *text_size, file_ptr *text_end));
+
+void
+NAME(aout,swap_exec_header_in) PARAMS ((bfd *abfd,
+ struct external_exec *raw_bytes, struct internal_exec *execp));
+
+void
+NAME(aout,swap_exec_header_out) PARAMS ((bfd *abfd,
+ struct internal_exec *execp, struct external_exec *raw_bytes));
+
+/* Prototypes for functions in stab-syms.c. */
+
+CONST char *
+aout_stab_name PARAMS ((int code));
+
+/* A.out uses the generic versions of these routines... */
+
+#define aout_32_get_section_contents bfd_generic_get_section_contents
+#define aout_32_close_and_cleanup bfd_generic_close_and_cleanup
+
+#define aout_64_get_section_contents bfd_generic_get_section_contents
+#define aout_64_close_and_cleanup bfd_generic_close_and_cleanup
+#ifndef NO_WRITE_HEADER_KLUDGE
+#define NO_WRITE_HEADER_KLUDGE 0
+#endif
+
+#ifndef WRITE_HEADERS
+#define WRITE_HEADERS(abfd, execp) \
+ { \
+ bfd_size_type text_size; /* dummy vars */ \
+ file_ptr text_end; \
+ if (adata(abfd).magic == undecided_magic) \
+ NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
+ \
+ execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
+ execp->a_entry = bfd_get_start_address (abfd); \
+ \
+ execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
+ obj_reloc_entry_size (abfd)); \
+ execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
+ obj_reloc_entry_size (abfd)); \
+ NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
+ \
+ bfd_seek (abfd, (file_ptr) 0, SEEK_SET); \
+ bfd_write ((PTR) &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, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET); \
+ \
+ NAME(aout,write_syms)(abfd); \
+ \
+ bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET); \
+ \
+ if (!NAME(aout,squirt_out_relocs) (abfd, obj_textsec (abfd))) return false; \
+ bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET); \
+ \
+ if (!NAME(aout,squirt_out_relocs)(abfd, obj_datasec (abfd))) return false; \
+ } \
+ }
+#endif
diff --git a/gnu/usr.bin/gdb/bfd/libbfd.c b/gnu/usr.bin/gdb/bfd/libbfd.c
new file mode 100644
index 000000000000..1bf8f7fb8e02
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/libbfd.c
@@ -0,0 +1,850 @@
+/* Assorted BFD support routines, only used internally.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/*
+SECTION
+ libbfd
+
+DESCRIPTION
+ This file contains various routines which are used within BFD.
+ They are not intended for export, but are documented here for
+ completeness.
+*/
+
+boolean
+DEFUN(_bfd_dummy_new_section_hook,(ignore, ignore_newsect),
+ bfd *ignore AND
+ asection *ignore_newsect)
+{
+ return true;
+}
+
+boolean
+DEFUN(bfd_false ,(ignore),
+ bfd *ignore)
+{
+ return false;
+}
+
+boolean
+DEFUN(bfd_true,(ignore),
+ bfd *ignore)
+{
+ return true;
+}
+
+PTR
+DEFUN(bfd_nullvoidptr,(ignore),
+ bfd *ignore)
+{
+ return (PTR)NULL;
+}
+
+int
+DEFUN(bfd_0,(ignore),
+ bfd *ignore)
+{
+ return 0;
+}
+
+unsigned int
+DEFUN(bfd_0u,(ignore),
+ bfd *ignore)
+{
+ return 0;
+}
+
+void
+DEFUN(bfd_void,(ignore),
+ bfd *ignore)
+{
+}
+
+boolean
+DEFUN(_bfd_dummy_core_file_matches_executable_p,(ignore_core_bfd, ignore_exec_bfd),
+ bfd *ignore_core_bfd AND
+ 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 *
+DEFUN(_bfd_dummy_core_file_failing_command,(ignore_abfd),
+ bfd *ignore_abfd)
+{
+ return (char *)NULL;
+}
+
+int
+DEFUN(_bfd_dummy_core_file_failing_signal,(ignore_abfd),
+ bfd *ignore_abfd)
+{
+ return 0;
+}
+
+bfd_target *
+DEFUN(_bfd_dummy_target,(ignore_abfd),
+ bfd *ignore_abfd)
+{
+ return 0;
+}
+
+/** zalloc -- allocate and clear storage */
+
+
+#ifndef zalloc
+char *
+DEFUN(zalloc,(size),
+ bfd_size_type size)
+{
+ char *ptr = (char *) malloc ((size_t)size);
+
+ if ((ptr != NULL) && (size != 0))
+ memset(ptr,0, (size_t) size);
+
+ return ptr;
+}
+#endif
+
+/*
+INTERNAL_FUNCTION
+ bfd_xmalloc
+
+SYNOPSIS
+ PTR bfd_xmalloc( bfd_size_type size);
+
+DESCRIPTION
+ Like malloc, but exit if no more memory.
+
+*/
+
+/** There is major inconsistency in how running out of memory is handled.
+ Some routines return a NULL, and set bfd_error to no_memory.
+ However, obstack routines can't do this ... */
+
+
+DEFUN(PTR bfd_xmalloc,(size),
+ bfd_size_type size)
+{
+ static CONST char no_memory_message[] = "Virtual memory exhausted!\n";
+ PTR ptr;
+ if (size == 0) size = 1;
+ ptr = (PTR)malloc((size_t) size);
+ if (!ptr)
+ {
+ write (2, no_memory_message, sizeof(no_memory_message)-1);
+ exit (-1);
+ }
+ return ptr;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_xmalloc_by_size_t
+
+SYNOPSIS
+ PTR bfd_xmalloc_by_size_t ( size_t size);
+
+DESCRIPTION
+ Like malloc, but exit if no more memory.
+ Uses size_t, so it's suitable for use as obstack_chunk_alloc.
+ */
+PTR
+DEFUN(bfd_xmalloc_by_size_t, (size),
+ size_t size)
+{
+ return bfd_xmalloc ((bfd_size_type) size);
+}
+
+/* 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. */
+
+static
+int DEFUN(real_read,(where, a,b, file),
+ PTR where AND
+ int a AND
+ int b AND
+ FILE *file)
+{
+ return fread(where, a,b,file);
+}
+bfd_size_type
+DEFUN(bfd_read,(ptr, size, nitems, abfd),
+ PTR ptr AND
+ bfd_size_type size AND
+ bfd_size_type nitems AND
+ bfd *abfd)
+{
+ int nread;
+ nread = real_read (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd));
+#ifdef FILE_OFFSET_IS_CHAR_INDEX
+ if (nread > 0)
+ abfd->where += nread;
+#endif
+ return nread;
+}
+
+bfd_size_type
+DEFUN(bfd_write,(ptr, size, nitems, abfd),
+ CONST PTR ptr AND
+ bfd_size_type size AND
+ bfd_size_type nitems AND
+ bfd *abfd)
+{
+ int nwrote = fwrite (ptr, 1, (int)(size*nitems), bfd_cache_lookup(abfd));
+#ifdef FILE_OFFSET_IS_CHAR_INDEX
+ if (nwrote > 0)
+ abfd->where += nwrote;
+#endif
+ return nwrote;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_write_bigendian_4byte_int
+
+SYNOPSIS
+ void bfd_write_bigendian_4byte_int(bfd *abfd, int i);
+
+DESCRIPTION
+ Writes a 4 byte integer to the outputing bfd, in big endian
+ mode regardless of what else is going on. This is useful in
+ archives.
+
+*/
+void
+DEFUN(bfd_write_bigendian_4byte_int,(abfd, i),
+ bfd *abfd AND
+ int i)
+{
+ bfd_byte buffer[4];
+ bfd_putb32(i, buffer);
+ bfd_write((PTR)buffer, 4, 1, abfd);
+}
+
+long
+DEFUN(bfd_tell,(abfd),
+ bfd *abfd)
+{
+ file_ptr ptr;
+
+ ptr = ftell (bfd_cache_lookup(abfd));
+
+ if (abfd->my_archive)
+ ptr -= abfd->origin;
+ abfd->where = ptr;
+ return ptr;
+}
+
+int
+DEFUN(bfd_flush,(abfd),
+ bfd *abfd)
+{
+ return fflush (bfd_cache_lookup(abfd));
+}
+
+int
+DEFUN(bfd_stat,(abfd, statbuf),
+ bfd *abfd AND
+ struct stat *statbuf)
+{
+ return fstat (fileno(bfd_cache_lookup(abfd)), statbuf);
+}
+
+int
+DEFUN(bfd_seek,(abfd, position, direction),
+ bfd * CONST abfd AND
+ CONST file_ptr position AND
+ CONST int direction)
+{
+ int result;
+ FILE *f;
+ file_ptr file_position;
+ /* 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_CUR && position == 0)
+ return 0;
+#ifdef FILE_OFFSET_IS_CHAR_INDEX
+ if (abfd->format != bfd_archive && abfd->my_archive == 0)
+ {
+#ifndef NDEBUG
+ /* Explanation for this code: I'm only about 95+% sure that the above
+ conditions are sufficient and that all i/o calls are properly
+ adjusting the `where' field. So this is sort of an `assert'
+ that the `where' field is correct. If we can go a while without
+ tripping the abort, we can probably safely disable this code,
+ so that the real optimizations happen. */
+ file_ptr where_am_i_now;
+ where_am_i_now = ftell (bfd_cache_lookup (abfd));
+ if (abfd->my_archive)
+ where_am_i_now -= abfd->origin;
+ if (where_am_i_now != abfd->where)
+ abort ();
+#endif
+ if (direction == SEEK_SET && position == abfd->where)
+ return 0;
+ }
+ else
+ {
+ /* We need something smarter to optimize access to archives.
+ Currently, anything inside an archive is read via the file
+ handle for the archive. Which means that a bfd_seek on one
+ component affects the `current position' in the archive, as
+ well as in any other component.
+
+ It might be sufficient to put a spike through the cache
+ abstraction, and look to the archive for the file position,
+ but I think we should try for something cleaner.
+
+ In the meantime, no optimization for archives. */
+ }
+#endif
+
+ f = bfd_cache_lookup (abfd);
+ file_position = position;
+ if (direction == SEEK_SET && abfd->my_archive != NULL)
+ file_position += abfd->origin;
+
+ result = fseek (f, file_position, direction);
+
+ if (result != 0)
+ /* Force redetermination of `where' field. */
+ bfd_tell (abfd);
+ else
+ {
+#ifdef FILE_OFFSET_IS_CHAR_INDEX
+ /* Adjust `where' field. */
+ if (direction == SEEK_SET)
+ abfd->where = position;
+ else
+ abfd->where += position;
+#endif
+ }
+ return result;
+}
+
+/** Make a string table */
+
+/*>bfd.h<
+ 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
+DEFUN(bfd_add_to_string_table,(table, new_string, table_length, free_ptr),
+ char **table AND
+ char *new_string AND
+ unsigned int *table_length AND
+ char **free_ptr)
+{
+ 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 ((bfd_size_type) 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;
+}
+
+/** 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. */
+
+/*
+FUNCTION
+ bfd_put_size
+FUNCTION
+ bfd_get_size
+
+DESCRIPTION
+ These macros as used for reading and writing raw data in
+ sections; each access (except for bytes) is vectored through
+ the target format of the BFD and mangled accordingly. The
+ mangling performs any necessary endian translations and
+ removes alignment restrictions. Note that types accepted and
+ returned by these macros are identical so they can be swapped
+ around in macros--for example libaout.h defines GET_WORD to
+ either bfd_get_32 or bfd_get_64.
+
+ In the put routines, val must be a bfd_vma. If we are on a
+ system without prototypes, the caller is responsible for making
+ sure that is true, with a cast if necessary. We don't cast
+ them in the macro definitions because that would prevent lint
+ or gcc -Wall from detecting sins such as passing a pointer.
+ To detect calling these with less than a bfd_vma, use gcc
+ -Wconversion on a host with 64 bit bfd_vma's.
+
+.
+.{* Byte swapping macros for user section data. *}
+.
+.#define bfd_put_8(abfd, val, ptr) \
+. (*((unsigned char *)(ptr)) = (unsigned char)val)
+.#define bfd_put_signed_8 \
+. bfd_put_8
+.#define bfd_get_8(abfd, ptr) \
+. (*(unsigned char *)(ptr))
+.#define bfd_get_signed_8(abfd, ptr) \
+. ((*(unsigned char *)(ptr) ^ 0x80) - 0x80)
+.
+.#define bfd_put_16(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+.#define bfd_put_signed_16 \
+. bfd_put_16
+.#define bfd_get_16(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx16, (ptr))
+.#define bfd_get_signed_16(abfd, ptr) \
+. BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+.
+.#define bfd_put_32(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+.#define bfd_put_signed_32 \
+. bfd_put_32
+.#define bfd_get_32(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx32, (ptr))
+.#define bfd_get_signed_32(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+.
+.#define bfd_put_64(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+.#define bfd_put_signed_64 \
+. bfd_put_64
+.#define bfd_get_64(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx64, (ptr))
+.#define bfd_get_signed_64(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+.
+*/
+
+/*
+FUNCTION
+ bfd_h_put_size
+FUNCTION
+ bfd_h_get_size
+
+DESCRIPTION
+ These macros have the same function as their <<bfd_get_x>>
+ bretherin, except that they are used for removing information
+ for the header records of object files. Believe it or not,
+ some object files keep their header records in big endian
+ order, and their data in little endian order.
+.
+.{* Byte swapping macros for file header data. *}
+.
+.#define bfd_h_put_8(abfd, val, ptr) \
+. bfd_put_8 (abfd, val, ptr)
+.#define bfd_h_put_signed_8(abfd, val, ptr) \
+. bfd_put_8 (abfd, val, ptr)
+.#define bfd_h_get_8(abfd, ptr) \
+. bfd_get_8 (abfd, ptr)
+.#define bfd_h_get_signed_8(abfd, ptr) \
+. bfd_get_signed_8 (abfd, ptr)
+.
+.#define bfd_h_put_16(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_h_putx16,(val,ptr))
+.#define bfd_h_put_signed_16 \
+. bfd_h_put_16
+.#define bfd_h_get_16(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx16,(ptr))
+.#define bfd_h_get_signed_16(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr))
+.
+.#define bfd_h_put_32(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_h_putx32,(val,ptr))
+.#define bfd_h_put_signed_32 \
+. bfd_h_put_32
+.#define bfd_h_get_32(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx32,(ptr))
+.#define bfd_h_get_signed_32(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr))
+.
+.#define bfd_h_put_64(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_h_putx64,(val, ptr))
+.#define bfd_h_put_signed_64 \
+. bfd_h_put_64
+.#define bfd_h_get_64(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx64,(ptr))
+.#define bfd_h_get_signed_64(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr))
+.
+*/
+
+/* Sign extension to bfd_signed_vma. */
+#define COERCE16(x) (((bfd_signed_vma) (x) ^ 0x8000) - 0x8000)
+#define COERCE32(x) (((bfd_signed_vma) (x) ^ 0x80000000) - 0x80000000)
+#define EIGHT_GAZILLION (((HOST_64_BIT)0x80000000) << 32)
+#define COERCE64(x) \
+ (((bfd_signed_vma) (x) ^ EIGHT_GAZILLION) - EIGHT_GAZILLION)
+
+bfd_vma
+DEFUN(bfd_getb16,(addr),
+ register bfd_byte *addr)
+{
+ return (addr[0] << 8) | addr[1];
+}
+
+bfd_vma
+DEFUN(bfd_getl16,(addr),
+ register bfd_byte *addr)
+{
+ return (addr[1] << 8) | addr[0];
+}
+
+bfd_signed_vma
+DEFUN(bfd_getb_signed_16,(addr),
+ register bfd_byte *addr)
+{
+ return COERCE16((addr[0] << 8) | addr[1]);
+}
+
+bfd_signed_vma
+DEFUN(bfd_getl_signed_16,(addr),
+ register bfd_byte *addr)
+{
+ return COERCE16((addr[1] << 8) | addr[0]);
+}
+
+void
+DEFUN(bfd_putb16,(data, addr),
+ bfd_vma data AND
+ register bfd_byte *addr)
+{
+ addr[0] = (bfd_byte)(data >> 8);
+ addr[1] = (bfd_byte )data;
+}
+
+void
+DEFUN(bfd_putl16,(data, addr),
+ bfd_vma data AND
+ register bfd_byte *addr)
+{
+ addr[0] = (bfd_byte )data;
+ addr[1] = (bfd_byte)(data >> 8);
+}
+
+bfd_vma
+bfd_getb32 (addr)
+ register bfd_byte *addr;
+{
+ return (((((bfd_vma)addr[0] << 8) | addr[1]) << 8)
+ | addr[2]) << 8 | addr[3];
+}
+
+bfd_vma
+bfd_getl32 (addr)
+ register bfd_byte *addr;
+{
+ return (((((bfd_vma)addr[3] << 8) | addr[2]) << 8)
+ | addr[1]) << 8 | addr[0];
+}
+
+bfd_signed_vma
+bfd_getb_signed_32 (addr)
+ register bfd_byte *addr;
+{
+ return COERCE32((((((bfd_vma)addr[0] << 8) | addr[1]) << 8)
+ | addr[2]) << 8 | addr[3]);
+}
+
+bfd_signed_vma
+bfd_getl_signed_32 (addr)
+ register bfd_byte *addr;
+{
+ return COERCE32((((((bfd_vma)addr[3] << 8) | addr[2]) << 8)
+ | addr[1]) << 8 | addr[0]);
+}
+
+bfd_vma
+DEFUN(bfd_getb64,(addr),
+ register bfd_byte *addr)
+{
+#ifdef BFD64
+ bfd_vma low, high;
+
+ high= ((((((((addr[0]) << 8) |
+ addr[1]) << 8) |
+ addr[2]) << 8) |
+ addr[3]) );
+
+ low = (((((((((bfd_vma)addr[4]) << 8) |
+ addr[5]) << 8) |
+ addr[6]) << 8) |
+ addr[7]));
+
+ return high << 32 | low;
+#else
+ BFD_FAIL();
+ return 0;
+#endif
+
+}
+
+bfd_vma
+DEFUN(bfd_getl64,(addr),
+ register bfd_byte *addr)
+{
+
+#ifdef BFD64
+ bfd_vma low, high;
+ high= (((((((addr[7] << 8) |
+ addr[6]) << 8) |
+ addr[5]) << 8) |
+ addr[4]));
+
+ low = ((((((((bfd_vma)addr[3] << 8) |
+ addr[2]) << 8) |
+ addr[1]) << 8) |
+ addr[0]) );
+
+ return high << 32 | low;
+#else
+ BFD_FAIL();
+ return 0;
+#endif
+
+}
+
+bfd_signed_vma
+DEFUN(bfd_getb_signed_64,(addr),
+ register bfd_byte *addr)
+{
+#ifdef BFD64
+ bfd_vma low, high;
+
+ high= ((((((((addr[0]) << 8) |
+ addr[1]) << 8) |
+ addr[2]) << 8) |
+ addr[3]) );
+
+ low = (((((((((bfd_vma)addr[4]) << 8) |
+ addr[5]) << 8) |
+ addr[6]) << 8) |
+ addr[7]));
+
+ return COERCE64(high << 32 | low);
+#else
+ BFD_FAIL();
+ return 0;
+#endif
+
+}
+
+bfd_signed_vma
+DEFUN(bfd_getl_signed_64,(addr),
+ register bfd_byte *addr)
+{
+
+#ifdef BFD64
+ bfd_vma low, high;
+ high= (((((((addr[7] << 8) |
+ addr[6]) << 8) |
+ addr[5]) << 8) |
+ addr[4]));
+
+ low = ((((((((bfd_vma)addr[3] << 8) |
+ addr[2]) << 8) |
+ addr[1]) << 8) |
+ addr[0]) );
+
+ return COERCE64(high << 32 | low);
+#else
+ BFD_FAIL();
+ return 0;
+#endif
+
+}
+
+void
+DEFUN(bfd_putb32,(data, addr),
+ bfd_vma data AND
+ 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
+DEFUN(bfd_putl32,(data, addr),
+ bfd_vma data AND
+ 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);
+}
+void
+DEFUN(bfd_putb64,(data, addr),
+ bfd_vma data AND
+ register bfd_byte *addr)
+{
+#ifdef BFD64
+ addr[0] = (bfd_byte)(data >> (7*8));
+ addr[1] = (bfd_byte)(data >> (6*8));
+ addr[2] = (bfd_byte)(data >> (5*8));
+ addr[3] = (bfd_byte)(data >> (4*8));
+ addr[4] = (bfd_byte)(data >> (3*8));
+ addr[5] = (bfd_byte)(data >> (2*8));
+ addr[6] = (bfd_byte)(data >> (1*8));
+ addr[7] = (bfd_byte)(data >> (0*8));
+#else
+ BFD_FAIL();
+#endif
+
+}
+
+void
+DEFUN(bfd_putl64,(data, addr),
+ bfd_vma data AND
+ register bfd_byte *addr)
+{
+#ifdef BFD64
+ addr[7] = (bfd_byte)(data >> (7*8));
+ addr[6] = (bfd_byte)(data >> (6*8));
+ addr[5] = (bfd_byte)(data >> (5*8));
+ addr[4] = (bfd_byte)(data >> (4*8));
+ addr[3] = (bfd_byte)(data >> (3*8));
+ addr[2] = (bfd_byte)(data >> (2*8));
+ addr[1] = (bfd_byte)(data >> (1*8));
+ addr[0] = (bfd_byte)(data >> (0*8));
+#else
+ BFD_FAIL();
+#endif
+
+}
+
+
+/* Default implementation */
+
+boolean
+DEFUN(bfd_generic_get_section_contents, (abfd, section, location, offset, count),
+ bfd *abfd AND
+ sec_ptr section AND
+ PTR location AND
+ file_ptr offset AND
+ bfd_size_type count)
+{
+ if (count == 0)
+ return true;
+ if ((bfd_size_type)(offset+count) > section->_raw_size
+ || bfd_seek(abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1
+ || bfd_read(location, (bfd_size_type)1, count, abfd) != count)
+ return (false); /* on error */
+ return (true);
+}
+
+/* This generic function can only be used in implementations where creating
+ NEW sections is disallowed. It is useful in patching existing sections
+ in read-write files, though. See other set_section_contents functions
+ to see why it doesn't work for new sections. */
+boolean
+DEFUN(bfd_generic_set_section_contents, (abfd, section, location, offset, count),
+ bfd *abfd AND
+ sec_ptr section AND
+ PTR location AND
+ file_ptr offset AND
+ bfd_size_type count)
+{
+ if (count == 0)
+ return true;
+ if ((bfd_size_type)(offset+count) > bfd_get_section_size_after_reloc(section)
+ || bfd_seek(abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1
+ || bfd_write(location, (bfd_size_type)1, count, abfd) != count)
+ return (false); /* on error */
+ return (true);
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_log2
+
+DESCRIPTION
+ Return the log base 2 of the value supplied, rounded up. eg an
+ arg of 1025 would return 11.
+
+SYNOPSIS
+ unsigned int bfd_log2(bfd_vma x);
+*/
+
+unsigned
+bfd_log2(x)
+ bfd_vma x;
+{
+ unsigned result = 0;
+ while ( (bfd_vma)(1<< result) < x)
+ result++;
+ return result;
+}
diff --git a/gnu/usr.bin/gdb/bfd/libbfd.h b/gnu/usr.bin/gdb/bfd/libbfd.h
new file mode 100644
index 000000000000..fcd5bbca8de8
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/libbfd.h
@@ -0,0 +1,273 @@
+/* libbfd.h -- Declarations used by bfd library *implementation*.
+ (This include file is not for users of the library.)
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Align an address upward to a boundary, expressed as a number of bytes.
+ E.g. align to an 8-byte boundary with argument of 8. */
+#define BFD_ALIGN(this, boundary) \
+ ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
+
+/* If you want to read and write large blocks, you might want to do it
+ in quanta of this amount */
+#define DEFAULT_BUFFERSIZE 8192
+
+/* Set a tdata field. Can't use the other macros for this, since they
+ do casts, and casting to the left of assignment isn't portable. */
+#define set_tdata(bfd, v) ((bfd)->tdata.any = (PTR) (v))
+
+/* 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 */
+ time_t armap_timestamp; /* Timestamp value written into armap.
+ This is used for BSD archives to check
+ that the timestamp is recent enough
+ for the BSD linker to not complain,
+ just before we finish writing an
+ archive. */
+ file_ptr armap_datepos; /* Position within archive to seek to
+ rewrite the date field. */
+};
+
+#define bfd_ardata(bfd) ((bfd)->tdata.aout_ar_data)
+
+/* 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)
+
+char *zalloc PARAMS ((bfd_size_type size));
+
+/* These routines allocate and free things on the BFD's obstack. Note
+ that realloc can never occur in place. */
+
+PTR bfd_alloc PARAMS ((bfd *abfd, size_t size));
+PTR bfd_zalloc PARAMS ((bfd *abfd, size_t size));
+PTR bfd_realloc PARAMS ((bfd *abfd, PTR orig, size_t new));
+void bfd_alloc_grow PARAMS ((bfd *abfd, PTR thing, size_t size));
+PTR bfd_alloc_finish PARAMS ((bfd *abfd));
+PTR bfd_alloc_by_size_t PARAMS ((bfd *abfd, size_t wanted));
+
+#define bfd_release(x,y) (void) obstack_free(&(x->memory),y)
+
+
+bfd_size_type bfd_read PARAMS ((PTR ptr, bfd_size_type size,
+ bfd_size_type nitems, bfd *abfd));
+bfd_size_type bfd_write PARAMS ((CONST PTR ptr, bfd_size_type size,
+ bfd_size_type nitems, bfd *abfd));
+int bfd_seek PARAMS ((bfd* CONST abfd, CONST file_ptr fp,
+ CONST int direction));
+long bfd_tell PARAMS ((bfd *abfd));
+
+int bfd_flush PARAMS ((bfd *abfd));
+int bfd_stat PARAMS ((bfd *abfd, struct stat *));
+
+bfd * _bfd_create_empty_archive_element_shell PARAMS ((bfd *obfd));
+bfd * look_for_bfd_in_cache PARAMS ((bfd *arch_bfd, file_ptr index));
+boolean _bfd_generic_mkarchive PARAMS ((bfd *abfd));
+struct areltdata * snarf_ar_hdr PARAMS ((bfd *abfd));
+bfd_target * bfd_generic_archive_p PARAMS ((bfd *abfd));
+boolean bfd_slurp_armap PARAMS ((bfd *abfd));
+boolean bfd_slurp_bsd_armap_f2 PARAMS ((bfd *abfd));
+#define bfd_slurp_bsd_armap bfd_slurp_armap
+#define bfd_slurp_coff_armap bfd_slurp_armap
+boolean _bfd_slurp_extended_name_table PARAMS ((bfd *abfd));
+boolean _bfd_write_archive_contents PARAMS ((bfd *abfd));
+bfd * new_bfd PARAMS (());
+
+#define DEFAULT_STRING_SPACE_SIZE 0x2000
+boolean bfd_add_to_string_table PARAMS ((char **table, char *new_string,
+ unsigned int *table_length,
+ char **free_ptr));
+
+boolean bfd_false PARAMS ((bfd *ignore));
+boolean bfd_true PARAMS ((bfd *ignore));
+PTR bfd_nullvoidptr PARAMS ((bfd *ignore));
+int bfd_0 PARAMS ((bfd *ignore));
+unsigned int bfd_0u PARAMS ((bfd *ignore));
+void bfd_void PARAMS ((bfd *ignore));
+
+bfd * new_bfd_contained_in PARAMS ((bfd *));
+boolean _bfd_dummy_new_section_hook PARAMS ((bfd *ignore, asection *newsect));
+char * _bfd_dummy_core_file_failing_command PARAMS ((bfd *abfd));
+int _bfd_dummy_core_file_failing_signal PARAMS ((bfd *abfd));
+boolean _bfd_dummy_core_file_matches_executable_p PARAMS ((bfd *core_bfd,
+ bfd *exec_bfd));
+bfd_target * _bfd_dummy_target PARAMS ((bfd *abfd));
+
+void bfd_dont_truncate_arname PARAMS ((bfd *abfd, CONST char *filename,
+ char *hdr));
+void bfd_bsd_truncate_arname PARAMS ((bfd *abfd, CONST char *filename,
+ char *hdr));
+void bfd_gnu_truncate_arname PARAMS ((bfd *abfd, CONST char *filename,
+ char *hdr));
+
+boolean bsd_write_armap PARAMS ((bfd *arch, unsigned int elength,
+ struct orl *map, unsigned int orl_count, int stridx));
+
+boolean coff_write_armap PARAMS ((bfd *arch, unsigned int elength,
+ struct orl *map, unsigned int orl_count, int stridx));
+
+bfd * bfd_generic_openr_next_archived_file PARAMS ((bfd *archive,
+ bfd *last_file));
+
+int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *));
+
+boolean bfd_generic_get_section_contents PARAMS ((bfd *abfd, sec_ptr section,
+ PTR location, file_ptr offset,
+ bfd_size_type count));
+
+boolean bfd_generic_set_section_contents PARAMS ((bfd *abfd, sec_ptr section,
+ PTR location, file_ptr offset,
+ bfd_size_type count));
+
+/* 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)
+
+void bfd_assert PARAMS ((char*,int));
+
+#define BFD_ASSERT(x) \
+{ if (!(x)) bfd_assert(__FILE__,__LINE__); }
+
+#define BFD_FAIL() \
+{ bfd_assert(__FILE__,__LINE__); }
+
+FILE * bfd_cache_lookup_worker PARAMS ((bfd *));
+
+extern bfd *bfd_last_cache;
+
+/* 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
+
+/* Generic routine for close_and_cleanup is really just bfd_true. */
+#define bfd_generic_close_and_cleanup bfd_true
+
+/* And more follows */
+
+void
+bfd_check_init PARAMS ((void));
+
+PTR
+bfd_xmalloc PARAMS (( bfd_size_type size));
+
+PTR
+bfd_xmalloc_by_size_t PARAMS (( size_t size));
+
+void
+bfd_write_bigendian_4byte_int PARAMS ((bfd *abfd, int i));
+
+unsigned int
+bfd_log2 PARAMS ((bfd_vma x));
+
+#define BFD_CACHE_MAX_OPEN 10
+extern bfd *bfd_last_cache;
+
+#define bfd_cache_lookup(x) \
+ ((x)==bfd_last_cache? \
+ (FILE*)(bfd_last_cache->iostream): \
+ bfd_cache_lookup_worker(x))
+boolean
+bfd_cache_close PARAMS ((bfd *));
+
+FILE*
+bfd_open_file PARAMS ((bfd *));
+
+FILE *
+bfd_cache_lookup_worker PARAMS ((bfd *));
+
+void
+bfd_constructor_entry PARAMS ((bfd *abfd,
+ asymbol **symbol_ptr_ptr,
+ CONST char*type));
+
+CONST struct reloc_howto_struct *
+bfd_default_reloc_type_lookup
+ PARAMS ((bfd *abfd AND
+ bfd_reloc_code_real_type code));
+
+boolean
+bfd_generic_relax_section
+ PARAMS ((bfd *abfd,
+ asection *section,
+ asymbol **symbols));
+
+bfd_byte *
+
+bfd_generic_get_relocated_section_contents PARAMS ((bfd *abfd,
+ struct bfd_seclet *seclet,
+ bfd_byte *data,
+ boolean relocateable));
+
+boolean
+bfd_generic_seclet_link
+ PARAMS ((bfd *abfd,
+ PTR data,
+ boolean relocateable));
+
+extern bfd_arch_info_type bfd_default_arch_struct;
+boolean
+bfd_default_set_arch_mach PARAMS ((bfd *abfd,
+ enum bfd_architecture arch,
+ unsigned long mach));
+
+void
+bfd_arch_init PARAMS ((void));
+
+void
+bfd_arch_linkin PARAMS ((bfd_arch_info_type *));
+
+CONST bfd_arch_info_type *
+bfd_default_compatible
+ PARAMS ((CONST bfd_arch_info_type *a,
+ CONST bfd_arch_info_type *b));
+
+boolean
+bfd_default_scan PARAMS ((CONST struct bfd_arch_info *, CONST char *));
+
+struct elf_internal_shdr *
+bfd_elf_find_section PARAMS ((bfd *abfd, char *name));
+
diff --git a/gnu/usr.bin/gdb/bfd/libcoff.h b/gnu/usr.bin/gdb/bfd/libcoff.h
new file mode 100644
index 000000000000..2aa6ad4b1615
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/libcoff.h
@@ -0,0 +1,352 @@
+/* BFD COFF object file private structure.
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* Object file tdata; access macros */
+
+#define coff_data(bfd) ((bfd)->tdata.coff_obj_data)
+#define exec_hdr(bfd) (coff_data(bfd)->hdr)
+#define obj_symbols(bfd) (coff_data(bfd)->symbols)
+#define obj_sym_filepos(bfd) (coff_data(bfd)->sym_filepos)
+
+#define obj_relocbase(bfd) (coff_data(bfd)->relocbase)
+#define obj_raw_syments(bfd) (coff_data(bfd)->raw_syments)
+#define obj_raw_syment_count(bfd) (coff_data(bfd)->raw_syment_count)
+#define obj_convert(bfd) (coff_data(bfd)->conversion_table)
+#define obj_conv_table_size(bfd) (coff_data(bfd)->conv_table_size)
+#if CFILE_STUFF
+#define obj_symbol_slew(bfd) (coff_data(bfd)->symbol_index_slew)
+#else
+#define obj_symbol_slew(bfd) 0
+#endif
+
+
+/* `Tdata' information kept for COFF files. */
+
+typedef struct coff_tdata
+{
+ struct coff_symbol_struct *symbols; /* symtab for input bfd */
+ unsigned int *conversion_table;
+ int conv_table_size;
+ file_ptr sym_filepos;
+
+ long symbol_index_slew; /* used during read to mark whether a
+ C_FILE symbol as been added. */
+
+ struct coff_ptr_struct *raw_syments;
+ struct lineno *raw_linenos;
+ unsigned int raw_syment_count;
+ unsigned short flags;
+
+ /* These are only valid once writing has begun */
+ long int relocbase;
+
+ /* These members communicate important constants about the symbol table
+ to GDB's symbol-reading code. These `constants' unfortunately vary
+ from coff implementation to implementation... */
+ unsigned local_n_btmask;
+ unsigned local_n_btshft;
+ unsigned local_n_tmask;
+ unsigned local_n_tshift;
+ unsigned local_symesz;
+ unsigned local_auxesz;
+ unsigned local_linesz;
+} coff_data_type;
+
+/* We take 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)))
+
+/* Functions in coffgen.c. */
+extern bfd_target *coff_object_p PARAMS ((bfd *));
+extern struct sec *coff_section_from_bfd_index PARAMS ((bfd *, int));
+extern unsigned int coff_get_symtab_upper_bound PARAMS ((bfd *));
+extern unsigned int coff_get_symtab PARAMS ((bfd *, asymbol **));
+extern int coff_count_linenumbers PARAMS ((bfd *));
+extern struct coff_symbol_struct *coff_symbol_from PARAMS ((bfd *, asymbol *));
+extern void coff_renumber_symbols PARAMS ((bfd *));
+extern void coff_mangle_symbols PARAMS ((bfd *));
+extern void coff_write_symbols PARAMS ((bfd *));
+extern void coff_write_linenumbers PARAMS ((bfd *));
+extern alent *coff_get_lineno PARAMS ((bfd *, asymbol *));
+extern asymbol *coff_section_symbol PARAMS ((bfd *, char *));
+extern struct coff_ptr_struct *coff_get_normalized_symtab PARAMS ((bfd *));
+extern unsigned int coff_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
+extern asymbol *coff_make_empty_symbol PARAMS ((bfd *));
+extern void coff_print_symbol PARAMS ((bfd *, PTR filep, asymbol *,
+ bfd_print_symbol_type how));
+extern void coff_get_symbol_info PARAMS ((bfd *, asymbol *,
+ symbol_info *ret));
+extern asymbol *coff_bfd_make_debug_symbol PARAMS ((bfd *, PTR,
+ unsigned long));
+extern boolean coff_find_nearest_line PARAMS ((bfd *,
+ asection *,
+ asymbol **,
+ bfd_vma offset,
+ CONST char **filename_ptr,
+ CONST char **functionname_ptr,
+ unsigned int *line_ptr));
+extern int coff_sizeof_headers PARAMS ((bfd *, boolean reloc));
+extern boolean bfd_coff_reloc16_relax_section PARAMS ((bfd *,
+ asection *,
+ asymbol **));
+extern bfd_byte *bfd_coff_reloc16_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_seclet *, bfd_byte *, boolean relocateable));
+extern bfd_vma bfd_coff_reloc16_get_value PARAMS ((arelent *,
+ struct bfd_seclet *));
+
+/* And more taken from the source .. */
+
+typedef struct coff_ptr_struct
+{
+
+ /* Remembers the offset from the first symbol in the file for
+ this symbol. Generated by coff_renumber_symbols. */
+unsigned int offset;
+
+ /* Should the tag field of this symbol be renumbered.
+ Created by coff_pointerize_aux. */
+char fix_tag;
+
+ /* Should the endidx field of this symbol be renumbered.
+ Created by coff_pointerize_aux. */
+char fix_end;
+
+ /* The container for the symbol structure as read and translated
+ from the file. */
+
+union {
+ union internal_auxent auxent;
+ struct internal_syment syment;
+ } u;
+} combined_entry_type;
+
+
+ /* Each canonical asymbol really looks like this: */
+
+typedef struct coff_symbol_struct
+{
+ /* The actual symbol which the rest of BFD works with */
+asymbol symbol;
+
+ /* A pointer to the hidden information for this symbol */
+combined_entry_type *native;
+
+ /* A pointer to the linenumber information for this symbol */
+struct lineno_cache_entry *lineno;
+
+ /* Have the line numbers been relocated yet ? */
+boolean done_lineno;
+} coff_symbol_type;
+typedef struct
+{
+ void (*_bfd_coff_swap_aux_in) PARAMS ((
+ bfd *abfd ,
+ PTR ext,
+ int type,
+ int class ,
+ PTR in));
+
+ void (*_bfd_coff_swap_sym_in) PARAMS ((
+ bfd *abfd ,
+ PTR ext,
+ PTR in));
+
+ void (*_bfd_coff_swap_lineno_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+
+ unsigned int (*_bfd_coff_swap_aux_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ int type,
+ int class,
+ PTR ext));
+
+ unsigned int (*_bfd_coff_swap_sym_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR ext));
+
+ unsigned int (*_bfd_coff_swap_lineno_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR ext));
+
+ unsigned int (*_bfd_coff_swap_reloc_out) PARAMS ((
+ bfd *abfd,
+ PTR src,
+ PTR dst));
+
+ unsigned int (*_bfd_coff_swap_filehdr_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR out));
+
+ unsigned int (*_bfd_coff_swap_aouthdr_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR out));
+
+ unsigned int (*_bfd_coff_swap_scnhdr_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR out));
+
+ unsigned int _bfd_filhsz;
+ unsigned int _bfd_aoutsz;
+ unsigned int _bfd_scnhsz;
+ unsigned int _bfd_symesz;
+ unsigned int _bfd_auxesz;
+ unsigned int _bfd_linesz;
+ boolean _bfd_coff_long_filenames;
+ void (*_bfd_coff_swap_filehdr_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+ void (*_bfd_coff_swap_aouthdr_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+ void (*_bfd_coff_swap_scnhdr_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+ boolean (*_bfd_coff_bad_format_hook) PARAMS ((
+ bfd *abfd,
+ PTR internal_filehdr));
+ boolean (*_bfd_coff_set_arch_mach_hook) PARAMS ((
+ bfd *abfd,
+ PTR internal_filehdr));
+ PTR (*_bfd_coff_mkobject_hook) PARAMS ((
+ bfd *abfd,
+ PTR internal_filehdr,
+ PTR internal_aouthdr));
+ flagword (*_bfd_styp_to_sec_flags_hook) PARAMS ((
+ bfd *abfd,
+ PTR internal_scnhdr));
+ asection *(*_bfd_make_section_hook) PARAMS ((
+ bfd *abfd,
+ char *name));
+ void (*_bfd_set_alignment_hook) PARAMS ((
+ bfd *abfd,
+ asection *sec,
+ PTR internal_scnhdr));
+ boolean (*_bfd_coff_slurp_symbol_table) PARAMS ((
+ bfd *abfd));
+ boolean (*_bfd_coff_symname_in_debug) PARAMS ((
+ bfd *abfd,
+ struct internal_syment *sym));
+ void (*_bfd_coff_reloc16_extra_cases) PARAMS ((
+ bfd *abfd,
+ struct bfd_seclet *seclet,
+ arelent *reloc,
+ bfd_byte *data,
+ unsigned int *src_ptr,
+ unsigned int *dst_ptr));
+ int (*_bfd_coff_reloc16_estimate) PARAMS ((
+ asection *input_section,
+ asymbol **symbols,
+ arelent *r,
+ unsigned int shrink));
+
+} bfd_coff_backend_data;
+
+#define coff_backend_info(abfd) ((bfd_coff_backend_data *) (abfd)->xvec->backend_data)
+
+#define bfd_coff_swap_aux_in(a,e,t,c,i) \
+ ((coff_backend_info (a)->_bfd_coff_swap_aux_in) (a,e,t,c,i))
+
+#define bfd_coff_swap_sym_in(a,e,i) \
+ ((coff_backend_info (a)->_bfd_coff_swap_sym_in) (a,e,i))
+
+#define bfd_coff_swap_lineno_in(a,e,i) \
+ ((coff_backend_info ( a)->_bfd_coff_swap_lineno_in) (a,e,i))
+
+#define bfd_coff_swap_reloc_out(abfd, i, o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_out) (abfd, i, o))
+
+#define bfd_coff_swap_lineno_out(abfd, i, o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_lineno_out) (abfd, i, o))
+
+#define bfd_coff_swap_aux_out(abfd, i, t,c,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_aux_out) (abfd, i,t,c, o))
+
+#define bfd_coff_swap_sym_out(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_sym_out) (abfd, i, o))
+
+#define bfd_coff_swap_scnhdr_out(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_out) (abfd, i, o))
+
+#define bfd_coff_swap_filehdr_out(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_out) (abfd, i, o))
+
+#define bfd_coff_swap_aouthdr_out(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_out) (abfd, i, o))
+
+#define bfd_coff_filhsz(abfd) (coff_backend_info (abfd)->_bfd_filhsz)
+#define bfd_coff_aoutsz(abfd) (coff_backend_info (abfd)->_bfd_aoutsz)
+#define bfd_coff_scnhsz(abfd) (coff_backend_info (abfd)->_bfd_scnhsz)
+#define bfd_coff_symesz(abfd) (coff_backend_info (abfd)->_bfd_symesz)
+#define bfd_coff_auxesz(abfd) (coff_backend_info (abfd)->_bfd_auxesz)
+#define bfd_coff_linesz(abfd) (coff_backend_info (abfd)->_bfd_linesz)
+#define bfd_coff_long_filenames(abfd) (coff_backend_info (abfd)->_bfd_coff_long_filenames)
+#define bfd_coff_swap_filehdr_in(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_in) (abfd, i, o))
+
+#define bfd_coff_swap_aouthdr_in(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_in) (abfd, i, o))
+
+#define bfd_coff_swap_scnhdr_in(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_in) (abfd, i, o))
+
+#define bfd_coff_bad_format_hook(abfd, filehdr) \
+ ((coff_backend_info (abfd)->_bfd_coff_bad_format_hook) (abfd, filehdr))
+
+#define bfd_coff_set_arch_mach_hook(abfd, filehdr)\
+ ((coff_backend_info (abfd)->_bfd_coff_set_arch_mach_hook) (abfd, filehdr))
+#define bfd_coff_mkobject_hook(abfd, filehdr, aouthdr)\
+ ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook) (abfd, filehdr, aouthdr))
+
+#define bfd_coff_styp_to_sec_flags_hook(abfd, scnhdr)\
+ ((coff_backend_info (abfd)->_bfd_styp_to_sec_flags_hook) (abfd, scnhdr))
+
+#define bfd_coff_make_section_hook(abfd, name)\
+ ((coff_backend_info (abfd)->_bfd_make_section_hook) (abfd, name))
+
+#define bfd_coff_set_alignment_hook(abfd, sec, scnhdr)\
+ ((coff_backend_info (abfd)->_bfd_set_alignment_hook) (abfd, sec, scnhdr))
+
+#define bfd_coff_slurp_symbol_table(abfd)\
+ ((coff_backend_info (abfd)->_bfd_coff_slurp_symbol_table) (abfd))
+
+#define bfd_coff_symname_in_debug(abfd, sym)\
+ ((coff_backend_info (abfd)->_bfd_coff_symname_in_debug) (abfd, sym))
+
+#define bfd_coff_reloc16_extra_cases(abfd, seclet, reloc, data, src_ptr, dst_ptr)\
+ ((coff_backend_info (abfd)->_bfd_coff_reloc16_extra_cases)\
+ (abfd, seclet, reloc, data, src_ptr, dst_ptr))
+
+#define bfd_coff_reloc16_estimate(abfd, section, symbols, reloc, shrink)\
+ ((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\
+ (section, symbols, reloc, shrink))
+
+
diff --git a/gnu/usr.bin/gdb/bfd/libecoff.h b/gnu/usr.bin/gdb/bfd/libecoff.h
new file mode 100644
index 000000000000..ad3e8f223aa4
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/libecoff.h
@@ -0,0 +1,265 @@
+/* BFD ECOFF object file private structure.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is the backend information kept for ECOFF files. This
+ structure is constant for a particular backend. The first element
+ is the COFF backend data structure, so that ECOFF targets can use
+ the generic COFF code. */
+
+#define ecoff_backend(abfd) \
+ ((struct ecoff_backend_data *) (abfd)->xvec->backend_data)
+
+struct ecoff_backend_data
+{
+ /* COFF backend information. This must be the first field. */
+ bfd_coff_backend_data coff;
+ /* Supported architecture. */
+ enum bfd_architecture arch;
+ /* Symbol table magic number. */
+ int sym_magic;
+ /* Initial portion of armap string. */
+ const char *armap_start;
+ /* Alignment of debugging information. E.g., 4. */
+ bfd_size_type debug_align;
+ /* The page boundary used to align sections in a demand-paged
+ executable file. E.g., 0x1000. */
+ bfd_vma round;
+ /* Bitsize of constructor entries. */
+ unsigned int constructor_bitsize;
+ /* Reloc to use for constructor entries. */
+ CONST struct reloc_howto_struct *constructor_reloc;
+ /* Sizes of external symbolic information. */
+ bfd_size_type external_hdr_size;
+ bfd_size_type external_dnr_size;
+ bfd_size_type external_pdr_size;
+ bfd_size_type external_sym_size;
+ bfd_size_type external_opt_size;
+ bfd_size_type external_fdr_size;
+ bfd_size_type external_rfd_size;
+ bfd_size_type external_ext_size;
+ /* Functions to swap in external symbolic data. */
+ void (*swap_hdr_in) PARAMS ((bfd *, PTR, HDRR *));
+ void (*swap_dnr_in) PARAMS ((bfd *, PTR, DNR *));
+ void (*swap_pdr_in) PARAMS ((bfd *, PTR, PDR *));
+ void (*swap_sym_in) PARAMS ((bfd *, PTR, SYMR *));
+ void (*swap_opt_in) PARAMS ((bfd *, PTR, OPTR *));
+ void (*swap_fdr_in) PARAMS ((bfd *, PTR, FDR *));
+ void (*swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *));
+ void (*swap_ext_in) PARAMS ((bfd *, PTR, EXTR *));
+ /* Functions to swap out external symbolic data. */
+ void (*swap_hdr_out) PARAMS ((bfd *, const HDRR *, PTR));
+ void (*swap_dnr_out) PARAMS ((bfd *, const DNR *, PTR));
+ void (*swap_pdr_out) PARAMS ((bfd *, const PDR *, PTR));
+ void (*swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR));
+ void (*swap_opt_out) PARAMS ((bfd *, const OPTR *, PTR));
+ void (*swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR));
+ void (*swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR));
+ void (*swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR));
+ /* It so happens that the auxiliary type information has the same
+ type and format for all known ECOFF targets. I don't see any
+ reason that that should change, so at least for now the auxiliary
+ swapping information is not in this table. */
+ /* External reloc size. */
+ bfd_size_type external_reloc_size;
+ /* Reloc swapping functions. */
+ void (*swap_reloc_in) PARAMS ((bfd *, PTR, struct internal_reloc *));
+ void (*swap_reloc_out) PARAMS ((bfd *, const struct internal_reloc *, PTR));
+ /* Backend reloc tweaking. */
+ void (*finish_reloc) PARAMS ((bfd *, struct internal_reloc *, arelent *));
+};
+
+/* This is the target specific information kept for ECOFF files. */
+
+#define ecoff_data(abfd) ((abfd)->tdata.ecoff_obj_data)
+
+typedef struct ecoff_tdata
+{
+ /* The reloc file position, set by
+ ecoff_compute_section_file_positions. */
+ file_ptr reloc_filepos;
+
+ /* The symbol table file position, set by ecoff_mkobject_hook. */
+ file_ptr sym_filepos;
+
+ /* The start and end of the text segment. Only valid for an
+ existing file, not for one we are creating. */
+ unsigned long text_start;
+ unsigned long text_end;
+
+ /* The cached gp value. This is used when relocating. */
+ bfd_vma gp;
+
+ /* The maximum size of objects to optimize using gp. This is
+ typically set by the -G option to the compiler, assembler or
+ linker. */
+ int gp_size;
+
+ /* The register masks. When linking, all the masks found in the
+ input files are combined into the masks of the output file.
+ These are not all used for all targets, but that's OK, because
+ the relevant ones are the only ones swapped in and out. */
+ unsigned long gprmask;
+ unsigned long fprmask;
+ unsigned long cprmask[4];
+
+ /* The size of the unswapped ECOFF symbolic information. */
+ bfd_size_type raw_size;
+
+ /* The unswapped ECOFF symbolic information. */
+ PTR raw_syments;
+
+ /* The swapped ECOFF symbolic header. */
+ HDRR symbolic_header;
+
+ /* Pointers to the unswapped symbolic information. */
+ unsigned char *line;
+ PTR external_dnr; /* struct dnr_ext */
+ PTR external_pdr; /* struct pdr_ext */
+ PTR external_sym; /* struct sym_ext */
+ PTR external_opt; /* struct opt_ext */
+ union aux_ext *external_aux;
+ char *ss;
+ char *ssext;
+ PTR external_fdr; /* struct fdr_ext */
+ PTR external_rfd; /* struct rfd_ext */
+ PTR external_ext; /* struct ext_ext */
+
+ /* The swapped FDR information. */
+ FDR *fdr;
+
+ /* The FDR index. This is set for an input BFD to a link so that
+ the external symbols can set their FDR index correctly. */
+ unsigned int ifdbase;
+
+ /* The canonical BFD symbols. */
+ struct ecoff_symbol_struct *canonical_symbols;
+
+} ecoff_data_type;
+
+/* Each canonical asymbol really looks like this. */
+
+typedef struct ecoff_symbol_struct
+{
+ /* The actual symbol which the rest of BFD works with */
+ asymbol symbol;
+
+ /* The fdr for this symbol. */
+ FDR *fdr;
+
+ /* true if this is a local symbol rather than an external one. */
+ boolean local;
+
+ /* A pointer to the unswapped hidden information for this symbol.
+ This is either a struct sym_ext or a struct ext_ext, depending on
+ the value of the local field above. */
+ PTR native;
+} ecoff_symbol_type;
+
+/* We take the address of the first element of a asymbol to ensure that the
+ macro is only ever applied to an asymbol. */
+#define ecoffsymbol(asymbol) ((ecoff_symbol_type *) (&((asymbol)->the_bfd)))
+
+/* This is a hack borrowed from coffcode.h; we need to save the index
+ of an external symbol when we write it out so that can set the
+ symbol index correctly when we write out the relocs. */
+#define ecoff_get_sym_index(symbol) ((unsigned long) (symbol)->udata)
+#define ecoff_set_sym_index(symbol, idx) ((symbol)->udata = (PTR) (idx))
+
+/* Make an ECOFF object. */
+extern boolean ecoff_mkobject PARAMS ((bfd *));
+
+/* Read in the ECOFF symbolic debugging information. */
+extern boolean ecoff_slurp_symbolic_info PARAMS ((bfd *));
+
+/* Generic ECOFF BFD backend vectors. */
+extern asymbol *ecoff_make_empty_symbol PARAMS ((bfd *abfd));
+extern unsigned int ecoff_get_symtab_upper_bound PARAMS ((bfd *abfd));
+extern unsigned int ecoff_get_symtab PARAMS ((bfd *abfd,
+ asymbol **alocation));
+extern void ecoff_get_symbol_info PARAMS ((bfd *abfd,
+ asymbol *symbol,
+ symbol_info *ret));
+extern void ecoff_print_symbol PARAMS ((bfd *abfd, PTR filep,
+ asymbol *symbol,
+ bfd_print_symbol_type how));
+extern unsigned int ecoff_canonicalize_reloc PARAMS ((bfd *abfd,
+ asection *section,
+ arelent **relptr,
+ asymbol **symbols));
+extern boolean ecoff_find_nearest_line PARAMS ((bfd *abfd,
+ asection *section,
+ asymbol **symbols,
+ bfd_vma offset,
+ CONST char **filename_ptr,
+ CONST char **fnname_ptr,
+ unsigned int *retline_ptr));
+extern boolean ecoff_bfd_seclet_link PARAMS ((bfd *abfd, PTR data,
+ boolean relocateable));
+extern boolean ecoff_set_arch_mach PARAMS ((bfd *abfd,
+ enum bfd_architecture arch,
+ unsigned long machine));
+extern int ecoff_sizeof_headers PARAMS ((bfd *abfd, boolean reloc));
+extern boolean ecoff_set_section_contents PARAMS ((bfd *abfd,
+ asection *section,
+ PTR location,
+ file_ptr offset,
+ bfd_size_type count));
+extern boolean ecoff_get_section_contents PARAMS ((bfd *abfd,
+ asection *section,
+ PTR location,
+ file_ptr offset,
+ bfd_size_type count));
+extern boolean ecoff_write_object_contents PARAMS ((bfd *abfd));
+extern boolean ecoff_slurp_armap PARAMS ((bfd *abfd));
+extern boolean ecoff_write_armap PARAMS ((bfd *abfd, unsigned int elength,
+ struct orl *map,
+ unsigned int orl_count,
+ int stridx));
+#define ecoff_slurp_extended_name_table _bfd_slurp_extended_name_table
+extern bfd_target *ecoff_archive_p PARAMS ((bfd *abfd));
+#define ecoff_get_lineno \
+ ((alent *(*) PARAMS ((bfd *, asymbol *))) bfd_nullvoidptr)
+#define ecoff_truncate_arname bfd_dont_truncate_arname
+#define ecoff_openr_next_archived_file bfd_generic_openr_next_archived_file
+#define ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define ecoff_get_reloc_upper_bound coff_get_reloc_upper_bound
+#define ecoff_close_and_cleanup bfd_generic_close_and_cleanup
+#define ecoff_bfd_debug_info_start bfd_void
+#define ecoff_bfd_debug_info_end bfd_void
+#define ecoff_bfd_debug_info_accumulate \
+ ((void (*) PARAMS ((bfd *, struct sec *))) bfd_void)
+#define ecoff_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define ecoff_bfd_relax_section bfd_generic_relax_section
+#define ecoff_bfd_make_debug_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+
+/* Hook functions for the generic COFF section reading code. */
+extern PTR ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr));
+extern asection *ecoff_make_section_hook PARAMS ((bfd *abfd, char *name));
+extern boolean ecoff_new_section_hook PARAMS ((bfd *abfd,
+ asection *section));
+#define ecoff_set_alignment_hook \
+ ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void)
+extern boolean ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr));
+extern long ecoff_sec_to_styp_flags PARAMS ((CONST char *name,
+ flagword flags));
+extern flagword ecoff_styp_to_sec_flags PARAMS ((bfd *abfd, PTR hdr));
+extern boolean ecoff_slurp_symbol_table PARAMS ((bfd *abfd));
diff --git a/gnu/usr.bin/gdb/bfd/libelf.h b/gnu/usr.bin/gdb/bfd/libelf.h
new file mode 100644
index 000000000000..187c51a29c0b
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/libelf.h
@@ -0,0 +1,249 @@
+/* BFD back-end data structures for ELF files.
+ Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _LIBELF_H_
+#define _LIBELF_H_ 1
+
+#include "elf/common.h"
+#include "elf/internal.h"
+#include "elf/external.h"
+
+/* If size isn't specified as 64 or 32, NAME macro should fail. */
+#ifndef NAME
+#if ARCH_SIZE==64
+#define NAME(x,y) CAT4(x,64,_,y)
+#endif
+#if ARCH_SIZE==32
+#define NAME(x,y) CAT4(x,32,_,y)
+#endif
+#endif
+
+#ifndef NAME
+#define NAME(x,y) CAT4(x,NOSIZE,_,y)
+#endif
+
+#define ElfNAME(X) NAME(Elf,X)
+#define elfNAME(X) NAME(elf,X)
+
+typedef struct
+{
+ asymbol symbol;
+ Elf_Internal_Sym internal_elf_sym;
+ union
+ {
+ unsigned int hppa_arg_reloc;
+ PTR any;
+ }
+ tc_data;
+} elf_symbol_type;
+
+struct elf_backend_data
+{
+ int use_rela_p;
+ int elf_64_p;
+ enum bfd_architecture arch;
+ void (*elf_info_to_howto) PARAMS ((bfd *, arelent *,
+ Elf_Internal_Rela *));
+ void (*elf_info_to_howto_rel) PARAMS ((bfd *, arelent *,
+ Elf_Internal_Rel *));
+ bfd_vma maxpagesize;
+ void (*write_relocs) PARAMS ((bfd *, asection *, PTR));
+
+ void (*elf_backend_symbol_processing) PARAMS ((bfd *, asymbol *));
+ boolean (*elf_backend_symbol_table_processing) PARAMS ((bfd *, elf_symbol_type *, int));
+ boolean (*elf_backend_section_processing) PARAMS ((bfd *, Elf32_Internal_Shdr *));
+ boolean (*elf_backend_section_from_shdr) PARAMS ((bfd *, Elf32_Internal_Shdr *, char *));
+ boolean (*elf_backend_fake_sections) PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
+ boolean (*elf_backend_section_from_bfd_section) PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *));
+};
+
+struct elf_sym_extra
+{
+ int elf_sym_num; /* sym# after locals/globals are reordered */
+};
+
+typedef struct elf_sym_extra Elf_Sym_Extra;
+
+struct bfd_elf_arch_map {
+ enum bfd_architecture bfd_arch;
+ int elf_arch;
+};
+
+extern const struct bfd_elf_arch_map bfd_elf_arch_map[];
+extern const int bfd_elf_arch_map_size;
+
+struct bfd_elf_section_data {
+ Elf_Internal_Shdr this_hdr;
+ Elf_Internal_Shdr rel_hdr;
+ int this_idx, rel_idx;
+};
+#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd)
+#define shdr_name(abfd,shdr) (elf_shstrtab (abfd)->tab + (shdr)->sh_name)
+
+#define get_elf_backend_data(abfd) \
+ ((struct elf_backend_data *) (abfd)->xvec->backend_data)
+
+struct strtab
+{
+ char *tab;
+ int nentries;
+ int length;
+};
+
+/* Some private data is stashed away for future use using the tdata pointer
+ in the bfd structure. */
+
+struct elf_obj_tdata
+{
+ Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */
+ Elf_Internal_Shdr **elf_sect_ptr;
+ Elf_Internal_Phdr *phdr;
+ struct strtab *strtab_ptr;
+ int num_locals;
+ int num_globals;
+ Elf_Internal_Sym *internal_syms;
+ elf_symbol_type *symbols; /* elf_symbol_type */
+ Elf_Sym_Extra *sym_extra;
+ asymbol **section_syms; /* STT_SECTION symbols for each section */
+ int num_section_syms; /* number of section_syms allocated */
+ Elf_Internal_Shdr symtab_hdr;
+ Elf_Internal_Shdr shstrtab_hdr;
+ Elf_Internal_Shdr strtab_hdr;
+ int symtab_section, shstrtab_section, strtab_section;
+ file_ptr next_file_pos;
+ void *prstatus; /* The raw /proc prstatus structure */
+ void *prpsinfo; /* The raw /proc prpsinfo structure */
+ bfd_vma gp; /* The gp value (MIPS only, for now) */
+ int gp_size; /* The gp size (MIPS only, for now) */
+};
+
+#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)
+#define elf_elfheader(bfd) (elf_tdata(bfd) -> elf_header)
+#define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr)
+#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr)
+#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section)
+#define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals)
+#define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals)
+#define elf_sym_extra(bfd) (elf_tdata(bfd) -> sym_extra)
+#define elf_section_syms(bfd) (elf_tdata(bfd) -> section_syms)
+#define elf_num_section_syms(bfd) (elf_tdata(bfd) -> num_section_syms)
+#define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo)
+#define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus)
+#define obj_symbols(bfd) (elf_tdata(bfd) -> symbols)
+#define obj_internal_syms(bfd) (elf_tdata(bfd) -> internal_syms)
+#define elf_gp(bfd) (elf_tdata(bfd) -> gp)
+#define elf_gp_size(bfd) (elf_tdata(bfd) -> gp_size)
+
+extern char * elf_string_from_elf_section PARAMS ((bfd *, unsigned, unsigned));
+extern char * elf_get_str_section PARAMS ((bfd *, unsigned));
+
+#define bfd_elf32_mkobject bfd_elf_mkobject
+#define bfd_elf64_mkobject bfd_elf_mkobject
+#define elf_mkobject bfd_elf_mkobject
+
+extern unsigned long bfd_elf_hash PARAMS ((CONST unsigned char *));
+
+extern bfd_reloc_status_type bfd_elf_generic_reloc PARAMS ((bfd *,
+ arelent *,
+ asymbol *,
+ PTR,
+ asection *,
+ bfd *));
+extern boolean bfd_elf_mkobject PARAMS ((bfd *));
+extern Elf_Internal_Shdr *bfd_elf_find_section PARAMS ((bfd *, char *));
+
+extern boolean bfd_elf32_write_object_contents PARAMS ((bfd *));
+extern boolean bfd_elf64_write_object_contents PARAMS ((bfd *));
+
+extern bfd_target *bfd_elf32_object_p PARAMS ((bfd *));
+extern bfd_target *bfd_elf32_core_file_p PARAMS ((bfd *));
+extern char *bfd_elf32_core_file_failing_command PARAMS ((bfd *));
+extern int bfd_elf32_core_file_failing_signal PARAMS ((bfd *));
+extern boolean bfd_elf32_core_file_matches_executable_p PARAMS ((bfd *,
+ bfd *));
+extern boolean bfd_elf32_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr,
+ bfd_size_type));
+
+extern unsigned int bfd_elf32_get_symtab_upper_bound PARAMS ((bfd *));
+extern unsigned int bfd_elf32_get_symtab PARAMS ((bfd *, asymbol **));
+extern unsigned int bfd_elf32_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
+extern unsigned int bfd_elf32_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
+ arelent **,
+ asymbol **));
+extern asymbol *bfd_elf32_make_empty_symbol PARAMS ((bfd *));
+extern void bfd_elf32_print_symbol PARAMS ((bfd *, PTR, asymbol *,
+ bfd_print_symbol_type));
+extern void bfd_elf32_get_symbol_info PARAMS ((bfd *, asymbol *,
+ symbol_info *));
+extern alent *bfd_elf32_get_lineno PARAMS ((bfd *, asymbol *));
+extern boolean bfd_elf32_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+extern boolean bfd_elf32_find_nearest_line PARAMS ((bfd *, asection *,
+ asymbol **,
+ bfd_vma, CONST char **,
+ CONST char **,
+ unsigned int *));
+extern int bfd_elf32_sizeof_headers PARAMS ((bfd *, boolean));
+extern void bfd_elf32__write_relocs PARAMS ((bfd *, asection *, PTR));
+extern boolean bfd_elf32_new_section_hook PARAMS ((bfd *, asection *));
+
+/* If the target doesn't have reloc handling written yet: */
+extern void bfd_elf32_no_info_to_howto PARAMS ((bfd *, arelent *,
+ Elf32_Internal_Rela *));
+
+extern bfd_target *bfd_elf64_object_p PARAMS ((bfd *));
+extern bfd_target *bfd_elf64_core_file_p PARAMS ((bfd *));
+extern char *bfd_elf64_core_file_failing_command PARAMS ((bfd *));
+extern int bfd_elf64_core_file_failing_signal PARAMS ((bfd *));
+extern boolean bfd_elf64_core_file_matches_executable_p PARAMS ((bfd *,
+ bfd *));
+extern boolean bfd_elf64_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr,
+ bfd_size_type));
+
+extern unsigned int bfd_elf64_get_symtab_upper_bound PARAMS ((bfd *));
+extern unsigned int bfd_elf64_get_symtab PARAMS ((bfd *, asymbol **));
+extern unsigned int bfd_elf64_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
+extern unsigned int bfd_elf64_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
+ arelent **,
+ asymbol **));
+extern asymbol *bfd_elf64_make_empty_symbol PARAMS ((bfd *));
+extern void bfd_elf64_print_symbol PARAMS ((bfd *, PTR, asymbol *,
+ bfd_print_symbol_type));
+extern void bfd_elf64_get_symbol_info PARAMS ((bfd *, asymbol *,
+ symbol_info *));
+extern alent *bfd_elf64_get_lineno PARAMS ((bfd *, asymbol *));
+extern boolean bfd_elf64_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+extern boolean bfd_elf64_find_nearest_line PARAMS ((bfd *, asection *,
+ asymbol **,
+ bfd_vma, CONST char **,
+ CONST char **,
+ unsigned int *));
+extern int bfd_elf64_sizeof_headers PARAMS ((bfd *, boolean));
+extern void bfd_elf64__write_relocs PARAMS ((bfd *, asection *, PTR));
+extern boolean bfd_elf64_new_section_hook PARAMS ((bfd *, asection *));
+
+/* If the target doesn't have reloc handling written yet: */
+extern void bfd_elf64_no_info_to_howto PARAMS ((bfd *, arelent *,
+ Elf64_Internal_Rela *));
+
+#endif /* _LIBELF_H_ */
diff --git a/gnu/usr.bin/gdb/bfd/opncls.c b/gnu/usr.bin/gdb/bfd/opncls.c
new file mode 100644
index 000000000000..42858c25919e
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/opncls.c
@@ -0,0 +1,534 @@
+/* opncls.c -- open and close a BFD.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+extern void bfd_cache_init PARAMS ((bfd *));
+FILE *bfd_open_file PARAMS ((bfd *));
+
+/* fdopen is a loser -- we should use stdio exclusively. Unfortunately
+ if we do that we can't use fcntl. */
+
+
+#define obstack_chunk_alloc bfd_xmalloc_by_size_t
+#define obstack_chunk_free free
+
+/* Return a new BFD. All BFD's are allocated through this routine. */
+
+bfd *
+new_bfd PARAMS ((void))
+{
+ bfd *nbfd;
+
+ nbfd = (bfd *)zalloc (sizeof (bfd));
+ if (!nbfd)
+ return 0;
+
+ bfd_check_init();
+ obstack_begin((PTR)&nbfd->memory, 128);
+
+ nbfd->arch_info = &bfd_default_arch_struct;
+
+ 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 = (PTR)NULL;
+ nbfd->cacheable = false;
+ nbfd->flags = NO_FLAGS;
+ nbfd->mtime_set = false;
+
+ return nbfd;
+}
+
+/* Allocate a new BFD as a member of archive OBFD. */
+
+bfd *
+new_bfd_contained_in (obfd)
+ bfd *obfd;
+{
+ bfd *nbfd;
+
+ nbfd = new_bfd();
+ nbfd->xvec = obfd->xvec;
+ nbfd->my_archive = obfd;
+ nbfd->direction = read_direction;
+ nbfd->target_defaulted = obfd->target_defaulted;
+ return nbfd;
+}
+
+/*
+SECTION
+ Opening and Closing BFDs
+
+*/
+
+/*
+FUNCTION
+ bfd_openr
+
+SYNOPSIS
+ bfd *bfd_openr(CONST char *filename, CONST char*target);
+
+DESCRIPTION
+ This function opens the file supplied (using <<fopen>>) with the target
+ supplied, it returns a pointer to the created BFD.
+
+ If NULL is returned then an error has occured. Possible errors
+ are <<no_memory>>, <<invalid_target>> or <<system_call>> error.
+*/
+
+bfd *
+DEFUN(bfd_openr, (filename, target),
+ CONST char *filename AND
+ CONST char *target)
+{
+ bfd *nbfd;
+ bfd_target *target_vec;
+
+ nbfd = new_bfd();
+ if (nbfd == NULL) {
+ bfd_error = no_memory;
+ return NULL;
+ }
+
+ target_vec = bfd_find_target (target, nbfd);
+ if (target_vec == NULL) {
+ bfd_error = invalid_target;
+ return NULL;
+ }
+
+ nbfd->filename = filename;
+ nbfd->direction = read_direction;
+
+ if (bfd_open_file (nbfd) == NULL) {
+ bfd_error = system_call_error; /* File didn't exist, or some such */
+ bfd_release(nbfd,0);
+ 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.
+ */
+/*
+FUNCTION
+ bfd_fdopenr
+
+SYNOPSIS
+ bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd);
+
+DESCRIPTION
+ bfd_fdopenr is to bfd_fopenr much like fdopen is to fopen.
+ It opens a BFD on a file already described by the @var{fd}
+ supplied.
+
+ When the file is later bfd_closed, the file descriptor will be closed.
+
+ If the caller desires that this file descriptor be cached by BFD
+ (opened as needed, closed as needed to free descriptors for
+ other opens), with the supplied @var{fd} used as an initial
+ file descriptor (but subject to closure at any time), set
+ bfd->cacheable nonzero in the returned BFD. The default is to
+ assume no cacheing; the file descriptor will remain open until
+ bfd_close, and will not be affected by BFD operations on other
+ files.
+
+ Possible errors are no_memory, invalid_target and system_call
+ error.
+*/
+
+bfd *
+DEFUN(bfd_fdopenr,(filename, target, fd),
+ CONST char *filename AND
+ CONST char *target AND
+ int fd)
+{
+ bfd *nbfd;
+ bfd_target *target_vec;
+ int fdflags;
+
+ bfd_error = system_call_error;
+
+#ifdef NO_FCNTL
+ fdflags = O_RDWR; /* Assume full access */
+#else
+ fdflags = fcntl (fd, F_GETFL, NULL);
+#endif
+ if (fdflags == -1) return NULL;
+
+ nbfd = new_bfd();
+
+ if (nbfd == NULL) {
+ bfd_error = no_memory;
+ return NULL;
+ }
+
+ target_vec = bfd_find_target (target, nbfd);
+ if (target_vec == NULL) {
+ bfd_error = invalid_target;
+ return NULL;
+ }
+#if defined(VMS) || defined(__GO32__)
+ nbfd->iostream = (char *)fopen(filename, FOPEN_RB);
+#else
+ /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
+ switch (fdflags & (O_ACCMODE)) {
+ case O_RDONLY: nbfd->iostream = (char *) fdopen (fd, FOPEN_RB); break;
+ case O_WRONLY: nbfd->iostream = (char *) fdopen (fd, FOPEN_RUB); break;
+ case O_RDWR: nbfd->iostream = (char *) fdopen (fd, FOPEN_RUB); break;
+ default: abort ();
+ }
+#endif
+ if (nbfd->iostream == NULL) {
+ (void) obstack_free (&nbfd->memory, (PTR)0);
+ return NULL;
+ }
+
+ /* OK, put everything where it belongs */
+
+ nbfd->filename = filename;
+
+ /* 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. */
+ /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
+ 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 ();
+ }
+
+ bfd_cache_init (nbfd);
+
+ return nbfd;
+}
+
+/** 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. */
+
+/*
+FUNCTION
+ bfd_openw
+
+SYNOPSIS
+ bfd *bfd_openw(CONST char *filename, CONST char *target);
+
+DESCRIPTION
+ Creates a BFD, associated with file @var{filename}, using the
+ file format @var{target}, and returns a pointer to it.
+
+ Possible errors are system_call_error, no_memory,
+ invalid_target.
+*/
+
+bfd *
+DEFUN(bfd_openw,(filename, target),
+ CONST char *filename AND
+ CONST char *target)
+{
+ bfd *nbfd;
+ bfd_target *target_vec;
+
+ 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;
+ }
+
+ target_vec = bfd_find_target (target, nbfd);
+ if (target_vec == NULL) return NULL;
+
+ nbfd->filename = filename;
+ nbfd->direction = write_direction;
+
+ if (bfd_open_file (nbfd) == NULL) {
+ bfd_error = system_call_error; /* File not writeable, etc */
+ (void) obstack_free (&nbfd->memory, (PTR)0);
+ return NULL;
+ }
+ return nbfd;
+}
+
+/*
+
+FUNCTION
+ bfd_close
+
+SYNOPSIS
+ boolean bfd_close(bfd *);
+
+DESCRIPTION
+
+ This function closes a BFD. If the BFD was open for writing,
+ then pending operations are completed and the file written out
+ and closed. If the created file is executable, then
+ <<chmod>> is called to mark it as such.
+
+ All memory attached to the BFD's obstacks is released.
+
+ The file descriptor associated with the BFD is closed (even
+ if it was passed in to BFD by bfd_fdopenr).
+
+RETURNS
+ <<true>> is returned if all is ok, otherwise <<false>>.
+*/
+
+
+boolean
+DEFUN(bfd_close,(abfd),
+ bfd *abfd)
+{
+ boolean ret;
+
+ if (!bfd_read_p(abfd))
+ if (BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)) != true)
+ return false;
+
+ if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
+
+ ret = bfd_cache_close(abfd);
+
+ /* If the file was open for writing and is now executable,
+ make it so */
+ if (ret == true
+ && abfd->direction == write_direction
+ && abfd->flags & EXEC_P) {
+ struct stat buf;
+ stat(abfd->filename, &buf);
+#ifndef S_IXUSR
+#define S_IXUSR 0100 /* Execute by owner. */
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010 /* Execute by group. */
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001 /* Execute by others. */
+#endif
+
+ chmod(abfd->filename, 0777 & (buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH));
+ }
+ (void) obstack_free (&abfd->memory, (PTR)0);
+ (void) free(abfd);
+ return ret;
+}
+
+/*
+FUNCTION
+ bfd_close_all_done
+
+SYNOPSIS
+ boolean bfd_close_all_done(bfd *);
+
+DESCRIPTION
+ This function closes a BFD. It differs from <<bfd_close>>
+ since it does not complete any pending operations. This
+ routine would be used if the application had just used BFD for
+ swapping and didn't want to use any of the writing code.
+
+ If the created file is executable, then <<chmod>> is called
+ to mark it as such.
+
+ All memory attached to the BFD's obstacks is released.
+
+RETURNS
+ <<true>> is returned if all is ok, otherwise <<false>>.
+
+*/
+
+boolean
+DEFUN(bfd_close_all_done,(abfd),
+ bfd *abfd)
+{
+ boolean ret;
+
+ ret = bfd_cache_close(abfd);
+
+ /* If the file was open for writing and is now executable,
+ make it so */
+ if (ret == true
+ && abfd->direction == write_direction
+ && abfd->flags & EXEC_P) {
+ struct stat buf;
+ stat(abfd->filename, &buf);
+#ifndef S_IXUSR
+#define S_IXUSR 0100 /* Execute by owner. */
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010 /* Execute by group. */
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001 /* Execute by others. */
+#endif
+
+ chmod(abfd->filename, 0x777 &(buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH));
+ }
+ (void) obstack_free (&abfd->memory, (PTR)0);
+ (void) free(abfd);
+ return ret;
+}
+
+
+/*
+FUNCTION
+ bfd_alloc_size
+
+SYNOPSIS
+ bfd_size_type bfd_alloc_size(bfd *abfd);
+
+DESCRIPTION
+ Return the number of bytes in the obstacks connected to the
+ supplied BFD.
+
+*/
+
+bfd_size_type
+DEFUN(bfd_alloc_size,(abfd),
+ bfd *abfd)
+{
+ struct _obstack_chunk *chunk = abfd->memory.chunk;
+ size_t size = 0;
+ while (chunk) {
+ size += chunk->limit - &(chunk->contents[0]);
+ chunk = chunk->prev;
+ }
+ return size;
+}
+
+
+
+/*
+FUNCTION
+ bfd_create
+
+SYNOPSIS
+ bfd *bfd_create(CONST char *filename, bfd *templ);
+
+DESCRIPTION
+ This routine creates a new BFD in the manner of
+ <<bfd_openw>>, but without opening a file. The new BFD
+ takes the target from the target used by @var{template}. The
+ format is always set to <<bfd_object>>.
+
+*/
+
+bfd *
+DEFUN(bfd_create,(filename, templ),
+ CONST char *filename AND
+ bfd *templ)
+{
+ bfd *nbfd = new_bfd();
+ if (nbfd == (bfd *)NULL) {
+ bfd_error = no_memory;
+ return (bfd *)NULL;
+ }
+ nbfd->filename = filename;
+ if(templ) {
+ nbfd->xvec = templ->xvec;
+ }
+ nbfd->direction = no_direction;
+ bfd_set_format(nbfd, bfd_object);
+ return nbfd;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_alloc_by_size_t
+
+SYNOPSIS
+ PTR bfd_alloc_by_size_t(bfd *abfd, size_t wanted);
+
+DESCRIPTION
+ This function allocates a block of memory in the obstack
+ attatched to <<abfd>> and returns a pointer to it.
+*/
+
+
+PTR
+DEFUN(bfd_alloc_by_size_t,(abfd, size),
+ bfd *abfd AND
+ size_t size)
+{
+ PTR res = obstack_alloc(&(abfd->memory), size);
+ return res;
+}
+
+DEFUN(void bfd_alloc_grow,(abfd, ptr, size),
+ bfd *abfd AND
+ PTR ptr AND
+ size_t size)
+{
+ (void) obstack_grow(&(abfd->memory), ptr, size);
+}
+DEFUN(PTR bfd_alloc_finish,(abfd),
+ bfd *abfd)
+{
+ return obstack_finish(&(abfd->memory));
+}
+
+DEFUN(PTR bfd_alloc, (abfd, size),
+ bfd *abfd AND
+ size_t size)
+{
+ return bfd_alloc_by_size_t(abfd, (size_t)size);
+}
+
+DEFUN(PTR bfd_zalloc,(abfd, size),
+ bfd *abfd AND
+ size_t size)
+{
+ PTR res;
+ res = bfd_alloc(abfd, size);
+ memset(res, 0, (size_t)size);
+ return res;
+}
+
+DEFUN(PTR bfd_realloc,(abfd, old, size),
+ bfd *abfd AND
+ PTR old AND
+ size_t size)
+{
+ PTR res = bfd_alloc(abfd, size);
+ memcpy(res, old, (size_t)size);
+ return res;
+}
diff --git a/gnu/usr.bin/gdb/bfd/reloc.c b/gnu/usr.bin/gdb/bfd/reloc.c
new file mode 100644
index 000000000000..f2dd5201d44b
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/reloc.c
@@ -0,0 +1,1225 @@
+/* BFD support for handling relocation entries.
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ Relocations
+
+ BFD maintains relocations in much the same was as it maintains
+ symbols; they are left alone until required, then read in
+ en-mass and traslated into an internal form. There is a common
+ routine <<bfd_perform_relocation>> which acts upon the
+ canonical form to do the actual fixup.
+
+ Note that relocations are maintained on a per section basis,
+ whilst symbols are maintained on a per BFD basis.
+
+ All a back end has to do to fit the BFD interface is to create
+ as many <<struct reloc_cache_entry>> as there are relocations
+ in a particular section, and fill in the right bits:
+
+@menu
+@* typedef arelent::
+@* howto manager::
+@end menu
+
+*/
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "seclet.h"
+/*
+DOCDD
+INODE
+ typedef arelent, howto manager, Relocations, Relocations
+
+SUBSECTION
+ typedef arelent
+
+ This is the structure of a relocation entry:
+
+CODE_FRAGMENT
+.
+.typedef enum bfd_reloc_status
+.{
+. {* No errors detected *}
+. bfd_reloc_ok,
+.
+. {* The relocation was performed, but there was an overflow. *}
+. bfd_reloc_overflow,
+.
+. {* The address to relocate was not within the section supplied. *}
+. bfd_reloc_outofrange,
+.
+. {* Used by special functions *}
+. bfd_reloc_continue,
+.
+. {* Unused *}
+. bfd_reloc_notsupported,
+.
+. {* Unsupported relocation size requested. *}
+. bfd_reloc_other,
+.
+. {* The symbol to relocate against was undefined. *}
+. bfd_reloc_undefined,
+.
+. {* The relocation was performed, but may not be ok - presently
+. generated only when linking i960 coff files with i960 b.out
+. symbols. *}
+. bfd_reloc_dangerous
+. }
+. bfd_reloc_status_type;
+.
+.
+.typedef struct reloc_cache_entry
+.{
+. {* A pointer into the canonical table of pointers *}
+. struct symbol_cache_entry **sym_ptr_ptr;
+.
+. {* offset in section *}
+. bfd_size_type address;
+.
+. {* addend for relocation value *}
+. bfd_vma addend;
+.
+. {* Pointer to how to perform the required relocation *}
+. CONST struct reloc_howto_struct *howto;
+.
+.} arelent;
+
+*/
+
+/*
+DESCRIPTION
+
+ Here is a description of each of the fields within a relent:
+
+ o sym_ptr_ptr
+
+ The symbol table pointer points to a pointer to the symbol
+ associated with the relocation request. This would naturally
+ be the pointer into the table returned by the back end's
+ get_symtab action. @xref{Symbols}. The symbol is referenced
+ through a pointer to a pointer so that tools like the linker
+ can fix up all the symbols of the same name by modifying only
+ one pointer. The relocation routine looks in the symbol and
+ uses the base of the section the symbol is attached to and the
+ value of the symbol as the initial relocation offset. If the
+ symbol pointer is zero, then the section provided is looked up.
+
+ o address
+
+ The address field gives the offset in bytes from the base of
+ the section data which owns the relocation record to the first
+ byte of relocatable information. The actual data relocated
+ will be relative to this point - for example, a relocation
+ type which modifies the bottom two bytes of a four byte word
+ would not touch the first byte pointed to in a big endian
+ world.
+
+ o addend
+
+ The addend is a value provided by the back end to be added (!)
+ to the relocation offset. Its interpretation is dependent upon
+ the howto. For example, on the 68k the code:
+
+
+| char foo[];
+| main()
+| {
+| return foo[0x12345678];
+| }
+
+ Could be compiled into:
+
+| linkw fp,#-4
+| moveb @@#12345678,d0
+| extbl d0
+| unlk fp
+| rts
+
+
+ This could create a reloc pointing to foo, but leave the
+ offset in the data (something like)
+
+
+|RELOCATION RECORDS FOR [.text]:
+|offset type value
+|00000006 32 _foo
+|
+|00000000 4e56 fffc ; linkw fp,#-4
+|00000004 1039 1234 5678 ; moveb @@#12345678,d0
+|0000000a 49c0 ; extbl d0
+|0000000c 4e5e ; unlk fp
+|0000000e 4e75 ; rts
+
+
+ Using coff and an 88k, some instructions don't have enough
+ space in them to represent the full address range, and
+ pointers have to be loaded in two parts. So you'd get something like:
+
+
+| or.u r13,r0,hi16(_foo+0x12345678)
+| ld.b r2,r13,lo16(_foo+0x12345678)
+| jmp r1
+
+
+ This should create two relocs, both pointing to _foo, and with
+ 0x12340000 in their addend field. The data would consist of:
+
+
+|RELOCATION RECORDS FOR [.text]:
+|offset type value
+|00000002 HVRT16 _foo+0x12340000
+|00000006 LVRT16 _foo+0x12340000
+
+|00000000 5da05678 ; or.u r13,r0,0x5678
+|00000004 1c4d5678 ; ld.b r2,r13,0x5678
+|00000008 f400c001 ; jmp r1
+
+
+ The relocation routine digs out the value from the data, adds
+ it to the addend to get the original offset and then adds the
+ value of _foo. Note that all 32 bits have to be kept around
+ somewhere, to cope with carry from bit 15 to bit 16.
+
+ One further example is the sparc and the a.out format. The
+ sparc has a similar problem to the 88k, in that some
+ instructions don't have room for an entire offset, but on the
+ sparc the parts are created odd sized lumps. The designers of
+ the a.out format chose not to use the data within the section
+ for storing part of the offset; all the offset is kept within
+ the reloc. Any thing in the data should be ignored.
+
+| save %sp,-112,%sp
+| sethi %hi(_foo+0x12345678),%g2
+| ldsb [%g2+%lo(_foo+0x12345678)],%i0
+| ret
+| restore
+
+ Both relocs contains a pointer to foo, and the offsets would
+ contain junk.
+
+
+|RELOCATION RECORDS FOR [.text]:
+|offset type value
+|00000004 HI22 _foo+0x12345678
+|00000008 LO10 _foo+0x12345678
+
+|00000000 9de3bf90 ; save %sp,-112,%sp
+|00000004 05000000 ; sethi %hi(_foo+0),%g2
+|00000008 f048a000 ; ldsb [%g2+%lo(_foo+0)],%i0
+|0000000c 81c7e008 ; ret
+|00000010 81e80000 ; restore
+
+
+ o howto
+
+ The howto field can be imagined as a
+ relocation instruction. It is a pointer to a struct which
+ contains information on what to do with all the other
+ information in the reloc record and data section. A back end
+ would normally have a relocation instruction set and turn
+ relocations into pointers to the correct structure on input -
+ but it would be possible to create each howto field on demand.
+
+*/
+
+/*
+SUBSUBSECTION
+ <<enum complain_overflow>>
+
+ Indicates what sort of overflow checking should be done when
+ performing a relocation.
+
+CODE_FRAGMENT
+.
+.enum complain_overflow
+.{
+. {* Do not complain on overflow. *}
+. complain_overflow_dont,
+.
+. {* Complain if the bitfield overflows, whether it is considered
+. as signed or unsigned. *}
+. complain_overflow_bitfield,
+.
+. {* Complain if the value overflows when considered as signed
+. number. *}
+. complain_overflow_signed,
+.
+. {* Complain if the value overflows when considered as an
+. unsigned number. *}
+. complain_overflow_unsigned
+.};
+
+*/
+
+/*
+SUBSUBSECTION
+ <<reloc_howto_type>>
+
+ The <<reloc_howto_type>> is a structure which contains all the
+ information that BFD needs to know to tie up a back end's data.
+
+CODE_FRAGMENT
+.struct symbol_cache_entry; {* Forward declaration *}
+.
+.typedef CONST struct reloc_howto_struct
+.{
+. {* The type field has mainly a documetary use - the back end can
+. to what it wants with it, though the normally the back end's
+. external idea of what a reloc number would be would be stored
+. in this field. For example, the a PC relative word relocation
+. in a coff environment would have the type 023 - because that's
+. what the outside world calls a R_PCRWORD reloc. *}
+. unsigned int type;
+.
+. {* The value the final relocation is shifted right by. This drops
+. unwanted data from the relocation. *}
+. unsigned int rightshift;
+.
+. {* The size of the item to be relocated. This is *not* a
+. power-of-two measure.
+. 0 : one byte
+. 1 : two bytes
+. 2 : four bytes
+. 3 : nothing done (unless special_function is nonzero)
+. 4 : eight bytes
+. -2 : two bytes, result should be subtracted from the
+. data instead of added
+. There is currently no trivial way to extract a "number of
+. bytes" from a howto pointer. *}
+. int size;
+.
+. {* The number of bits in the item to be relocated. This is used
+. when doing overflow checking. *}
+. unsigned int bitsize;
+.
+. {* Notes that the relocation is relative to the location in the
+. data section of the addend. The relocation function will
+. subtract from the relocation value the address of the location
+. being relocated. *}
+. boolean pc_relative;
+.
+. {* The bit position of the reloc value in the destination.
+. The relocated value is left shifted by this amount. *}
+. unsigned int bitpos;
+.
+. {* What type of overflow error should be checked for when
+. relocating. *}
+. enum complain_overflow complain_on_overflow;
+.
+. {* If this field is non null, then the supplied function is
+. called rather than the normal function. This allows really
+. strange relocation methods to be accomodated (e.g., i960 callj
+. instructions). *}
+. bfd_reloc_status_type (*special_function)
+. PARAMS ((bfd *abfd,
+. arelent *reloc_entry,
+. struct symbol_cache_entry *symbol,
+. PTR data,
+. asection *input_section,
+. bfd *output_bfd));
+.
+. {* The textual name of the relocation type. *}
+. char *name;
+.
+. {* When performing a partial link, some formats must modify the
+. relocations rather than the data - this flag signals this.*}
+. boolean partial_inplace;
+.
+. {* The src_mask is used to select what parts of the read in data
+. are to be used in the relocation sum. E.g., if this was an 8 bit
+. bit of data which we read and relocated, this would be
+. 0x000000ff. When we have relocs which have an addend, such as
+. sun4 extended relocs, the value in the offset part of a
+. relocating field is garbage so we never use it. In this case
+. the mask would be 0x00000000. *}
+. bfd_vma src_mask;
+.
+. {* The dst_mask is what parts of the instruction are replaced
+. into the instruction. In most cases src_mask == dst_mask,
+. except in the above special case, where dst_mask would be
+. 0x000000ff, and src_mask would be 0x00000000. *}
+. bfd_vma dst_mask;
+.
+. {* When some formats create PC relative instructions, they leave
+. the value of the pc of the place being relocated in the offset
+. slot of the instruction, so that a PC relative relocation can
+. be made just by adding in an ordinary offset (e.g., sun3 a.out).
+. Some formats leave the displacement part of an instruction
+. empty (e.g., m88k bcs), this flag signals the fact.*}
+. boolean pcrel_offset;
+.
+.} reloc_howto_type;
+
+*/
+
+/*
+FUNCTION
+ the HOWTO macro
+
+DESCRIPTION
+ The HOWTO define is horrible and will go away.
+
+
+.#define HOWTO(C, R,S,B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \
+. {(unsigned)C,R,S,B, P, BI, O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC}
+
+DESCRIPTION
+ And will be replaced with the totally magic way. But for the
+ moment, we are compatible, so do it this way..
+
+
+.#define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,complain_overflow_dont,FUNCTION, NAME,false,0,0,IN)
+.
+DESCRIPTION
+ Helper routine to turn a symbol into a relocation value.
+
+.#define HOWTO_PREPARE(relocation, symbol) \
+. { \
+. if (symbol != (asymbol *)NULL) { \
+. if (bfd_is_com_section (symbol->section)) { \
+. relocation = 0; \
+. } \
+. else { \
+. relocation = symbol->value; \
+. } \
+. } \
+.}
+
+*/
+
+/*
+TYPEDEF
+ reloc_chain
+
+DESCRIPTION
+
+ How relocs are tied together
+
+.typedef unsigned char bfd_byte;
+.
+.typedef struct relent_chain {
+. arelent relent;
+. struct relent_chain *next;
+.} arelent_chain;
+
+*/
+
+
+
+/*
+FUNCTION
+ bfd_perform_relocation
+
+SYNOPSIS
+ bfd_reloc_status_type
+ bfd_perform_relocation
+ (bfd * abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd);
+
+DESCRIPTION
+ 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 (e.g., 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_type
+DEFUN(bfd_perform_relocation,(abfd,
+ reloc_entry,
+ data,
+ input_section,
+ output_bfd),
+ bfd *abfd AND
+ arelent *reloc_entry AND
+ PTR data AND
+ asection *input_section AND
+ bfd *output_bfd)
+{
+ bfd_vma relocation;
+ bfd_reloc_status_type flag = bfd_reloc_ok;
+ bfd_size_type addr = reloc_entry->address ;
+ bfd_vma output_base = 0;
+ reloc_howto_type *howto = reloc_entry->howto;
+ asection *reloc_target_output_section ;
+
+ asymbol *symbol;
+
+ symbol = *( reloc_entry->sym_ptr_ptr);
+ if ((symbol->section == &bfd_abs_section)
+ && output_bfd != (bfd *)NULL)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* If we are not producing relocateable output, return an error if
+ the symbol is not defined. An undefined weak symbol is
+ considered to have a value of zero (SVR4 ABI, p. 4-27). */
+ if (symbol->section == &bfd_und_section
+ && (symbol->flags & BSF_WEAK) == 0
+ && output_bfd == (bfd *) NULL)
+ flag = bfd_reloc_undefined;
+
+ /* If there is a function supplied to handle this relocation type,
+ call it. It'll return `bfd_reloc_continue' if further processing
+ can be done. */
+ if (howto->special_function)
+ {
+ bfd_reloc_status_type cont;
+ cont = howto->special_function (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd);
+ if (cont != bfd_reloc_continue)
+ return cont;
+ }
+
+ /* Is the address of the relocation really within the section? */
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Work out which section the relocation is targetted at and the
+ initial relocation command value. */
+
+ /* Get symbol value. (Common symbols are special.) */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+
+ reloc_target_output_section = symbol->section->output_section;
+
+ /* Convert input-section-relative symbol value to absolute. */
+ if (output_bfd && howto->partial_inplace==false)
+ output_base = 0;
+ else
+ output_base = reloc_target_output_section->vma;
+
+ relocation += output_base + symbol->section->output_offset;
+
+ /* Add in supplied addend. */
+ relocation += reloc_entry->addend;
+
+ /* Here the variable relocation holds the final address of the
+ symbol we are relocating against, plus any addend. */
+
+ if (howto->pc_relative == true)
+ {
+ /* This is a PC relative relocation. We want to set RELOCATION
+ to the distance between the address of the symbol and the
+ location. RELOCATION is already the address of the symbol.
+
+ We start by subtracting the address of the section containing
+ the location.
+
+ If pcrel_offset is set, we must further subtract the position
+ of the location within the section. Some targets arrange for
+ the addend to be the negative of the position of the location
+ within the section; for example, i386-aout does this. For
+ i386-aout, pcrel_offset is false. Some other targets do not
+ include the position of the location; for example, m88kbcs,
+ or ELF. For those targets, pcrel_offset is true.
+
+ If we are producing relocateable output, then we must ensure
+ that this reloc will be correctly computed when the final
+ relocation is done. If pcrel_offset is false we want to wind
+ up with the negative of the location within the section,
+ which means we must adjust the existing addend by the change
+ in the location within the section. If pcrel_offset is true
+ we do not want to adjust the existing addend at all.
+
+ FIXME: This seems logical to me, but for the case of
+ producing relocateable output it is not what the code
+ actually does. I don't want to change it, because it seems
+ far too likely that something will break. */
+
+ relocation -=
+ input_section->output_section->vma + input_section->output_offset;
+
+ if (howto->pcrel_offset == true)
+ relocation -= reloc_entry->address;
+ }
+
+ if (output_bfd!= (bfd *)NULL)
+ {
+ if ( 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->address += input_section->output_offset;
+ return flag;
+ }
+ else
+ {
+ /* This is a partial relocation, but inplace, so modify the
+ reloc record a bit.
+
+ If we've relocated with a symbol with a section, change
+ into a ref to the section belonging to the symbol. */
+
+ reloc_entry->address += input_section->output_offset;
+
+ /* WTF?? */
+ if (abfd->xvec->flavour == bfd_target_coff_flavour)
+ {
+ relocation -= reloc_entry->addend;
+ reloc_entry->addend = 0;
+ }
+ else
+ {
+ reloc_entry->addend = relocation;
+ }
+ }
+ }
+ else
+ {
+ reloc_entry->addend = 0;
+ }
+
+ /* FIXME: This overflow checking is incomplete, because the value
+ might have overflowed before we get here. For a correct check we
+ need to compute the value in a size larger than bitsize, but we
+ can't reasonably do that for a reloc the same size as a host
+ machine word.
+ FIXME: We should also do overflow checking on the result after
+ adding in the value contained in the object file. */
+ if (howto->complain_on_overflow != complain_overflow_dont)
+ {
+ bfd_vma check;
+
+ /* Get the value that will be used for the relocation, but
+ starting at bit position zero. */
+ if (howto->rightshift > howto->bitpos)
+ check = relocation >> (howto->rightshift - howto->bitpos);
+ else
+ check = relocation << (howto->bitpos - howto->rightshift);
+ switch (howto->complain_on_overflow)
+ {
+ case complain_overflow_signed:
+ {
+ /* Assumes two's complement. */
+ bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
+ bfd_signed_vma reloc_signed_min = ~ reloc_signed_max;
+
+ /* The above right shift is incorrect for a signed value.
+ Fix it up by forcing on the upper bits. */
+ if (howto->rightshift > howto->bitpos
+ && (bfd_signed_vma) relocation < 0)
+ check |= ((bfd_vma) -1
+ &~ ((bfd_vma) -1
+ >> (howto->rightshift - howto->bitpos)));
+ if ((bfd_signed_vma) check > reloc_signed_max
+ || (bfd_signed_vma) check < reloc_signed_min)
+ flag = bfd_reloc_overflow;
+ }
+ break;
+ case complain_overflow_unsigned:
+ {
+ /* Assumes two's complement. This expression avoids
+ overflow if howto->bitsize is the number of bits in
+ bfd_vma. */
+ bfd_vma reloc_unsigned_max =
+ (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
+
+ if ((bfd_vma) check > reloc_unsigned_max)
+ flag = bfd_reloc_overflow;
+ }
+ break;
+ case complain_overflow_bitfield:
+ {
+ /* Assumes two's complement. This expression avoids
+ overflow if howto->bitsize is the number of bits in
+ bfd_vma. */
+ bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
+
+ if (((bfd_vma) check &~ reloc_bits) != 0
+ && ((bfd_vma) check &~ reloc_bits) != (-1 &~ reloc_bits))
+ {
+ /* The above right shift is incorrect for a signed
+ value. See if turning on the upper bits fixes the
+ overflow. */
+ if (howto->rightshift > howto->bitpos
+ && (bfd_signed_vma) relocation < 0)
+ {
+ check |= ((bfd_vma) -1
+ &~ ((bfd_vma) -1
+ >> (howto->rightshift - howto->bitpos)));
+ if (((bfd_vma) check &~ reloc_bits) != (-1 &~ reloc_bits))
+ flag = bfd_reloc_overflow;
+ }
+ else
+ flag = bfd_reloc_overflow;
+ }
+ }
+ break;
+ default:
+ abort ();
+ }
+ }
+
+ /*
+ 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;
+
+ /* Shift everything up to where it's going to be used */
+
+ relocation <<= howto->bitpos;
+
+ /* Wait for the day when all have the mask in them */
+
+ /* What we do:
+ i instruction to be left alone
+ o offset within instruction
+ r relocation offset to apply
+ S src mask
+ D dst mask
+ N ~dst mask
+ A part 1
+ B part 2
+ R result
+
+ Do this:
+ i i i i i o o o o o from bfd_get<size>
+ and S S S S S to get the size offset we want
+ + r r r r r r r r r r to get the final value to place
+ and D D D D D to chop to right size
+ -----------------------
+ A A A A A
+ And this:
+ ... i i i i i o o o o o from bfd_get<size>
+ and N N N N N get instruction
+ -----------------------
+ ... B B B B B
+
+ And then:
+ B B B B B
+ or A A A A A
+ -----------------------
+ R R R R R R R R R R put into bfd_put<size>
+ */
+
+#define DOIT(x) \
+ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8(abfd, (char *)data + addr);
+ DOIT(x);
+ bfd_put_8(abfd,x, (unsigned char *) data + addr);
+ }
+ break;
+
+ case 1:
+ if (relocation)
+ {
+ short x = bfd_get_16(abfd, (bfd_byte *)data + addr);
+ DOIT(x);
+ bfd_put_16(abfd, x, (unsigned char *)data + addr);
+ }
+ break;
+ case 2:
+ if (relocation)
+ {
+ long x = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+ DOIT (x);
+ bfd_put_32 (abfd, x, (bfd_byte *)data + addr);
+ }
+ break;
+ case -2:
+ {
+ long x = bfd_get_32(abfd, (bfd_byte *) data + addr);
+ relocation = -relocation;
+ DOIT(x);
+ bfd_put_32(abfd,x, (bfd_byte *)data + addr);
+ }
+ break;
+
+ case 3:
+ /* Do nothing */
+ break;
+
+ case 4:
+#ifdef BFD64
+ if (relocation)
+ {
+ bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + addr);
+ DOIT (x);
+ bfd_put_64 (abfd, x, (bfd_byte *) data + addr);
+ }
+#else
+ abort ();
+#endif
+ break;
+ default:
+ return bfd_reloc_other;
+ }
+
+ return flag;
+}
+
+
+
+/*
+DOCDD
+INODE
+ howto manager, , typedef arelent, Relocations
+
+SECTION
+ The howto manager
+
+ When an application wants to create a relocation, but doesn't
+ know what the target machine might call it, it can find out by
+ using this bit of code.
+
+*/
+
+/*
+TYPEDEF
+ bfd_reloc_code_type
+
+DESCRIPTION
+ The insides of a reloc code. The idea is that, eventually, there
+ will be one enumerator for every type of relocation we ever do.
+ Pass one of these values to <<bfd_reloc_type_lookup>>, and it'll
+ return a howto pointer.
+
+ This does mean that the application must determine the correct
+ enumerator value; you can't get a howto pointer from a random set
+ of attributes.
+
+CODE_FRAGMENT
+.
+.typedef enum bfd_reloc_code_real
+.{
+. {* Basic absolute relocations *}
+. BFD_RELOC_64,
+. BFD_RELOC_32,
+. BFD_RELOC_16,
+. BFD_RELOC_8,
+.
+. {* PC-relative relocations *}
+. BFD_RELOC_64_PCREL,
+. BFD_RELOC_32_PCREL,
+. BFD_RELOC_24_PCREL, {* used by i960 *}
+. BFD_RELOC_16_PCREL,
+. BFD_RELOC_8_PCREL,
+.
+. {* Linkage-table relative *}
+. BFD_RELOC_32_BASEREL,
+. BFD_RELOC_16_BASEREL,
+. BFD_RELOC_8_BASEREL,
+.
+. {* The type of reloc used to build a contructor table - at the moment
+. probably a 32 bit wide abs address, but the cpu can choose. *}
+. BFD_RELOC_CTOR,
+.
+. {* 8 bits wide, but used to form an address like 0xffnn *}
+. BFD_RELOC_8_FFnn,
+.
+. {* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit
+. word displacement, e.g. for SPARC) *}
+. BFD_RELOC_32_PCREL_S2,
+.
+. {* High 22 bits of 32-bit value, placed into lower 22 bits of
+. target word; simple reloc. *}
+. BFD_RELOC_HI22,
+. {* Low 10 bits. *}
+. BFD_RELOC_LO10,
+.
+. {* Reloc types used for i960/b.out. *}
+. BFD_RELOC_I960_CALLJ,
+.
+. {* now for the sparc/elf codes *}
+. BFD_RELOC_NONE, {* actually used *}
+. BFD_RELOC_SPARC_WDISP22,
+. BFD_RELOC_SPARC22,
+. BFD_RELOC_SPARC13,
+. BFD_RELOC_SPARC_GOT10,
+. BFD_RELOC_SPARC_GOT13,
+. BFD_RELOC_SPARC_GOT22,
+. BFD_RELOC_SPARC_PC10,
+. BFD_RELOC_SPARC_PC22,
+. BFD_RELOC_SPARC_WPLT30,
+. BFD_RELOC_SPARC_COPY,
+. BFD_RELOC_SPARC_GLOB_DAT,
+. BFD_RELOC_SPARC_JMP_SLOT,
+. BFD_RELOC_SPARC_RELATIVE,
+. BFD_RELOC_SPARC_UA32,
+.
+. {* these are a.out specific? *}
+. BFD_RELOC_SPARC_BASE13,
+. BFD_RELOC_SPARC_BASE22,
+.
+.
+. {* Bits 27..2 of the relocation address shifted right 2 bits;
+. simple reloc otherwise. *}
+. BFD_RELOC_MIPS_JMP,
+.
+. {* signed 16-bit pc-relative, shifted right 2 bits (e.g. for MIPS) *}
+. BFD_RELOC_16_PCREL_S2,
+.
+. {* High 16 bits of 32-bit value; simple reloc. *}
+. BFD_RELOC_HI16,
+. {* High 16 bits of 32-bit value but the low 16 bits will be sign
+. extended and added to form the final result. If the low 16
+. bits form a negative number, we need to add one to the high value
+. to compensate for the borrow when the low bits are added. *}
+. BFD_RELOC_HI16_S,
+. {* Low 16 bits. *}
+. BFD_RELOC_LO16,
+.
+. {* 16 bit relocation relative to the global pointer. *}
+. BFD_RELOC_MIPS_GPREL,
+.
+. {* These are, so far, specific to HPPA processors. I'm not sure that some
+. don't duplicate other reloc types, such as BFD_RELOC_32 and _32_PCREL.
+. Also, many more were in the list I got that don't fit in well in the
+. model BFD uses, so I've omitted them for now. If we do make this reloc
+. type get used for code that really does implement the funky reloc types,
+. they'll have to be added to this list. *}
+. BFD_RELOC_HPPA_32,
+. BFD_RELOC_HPPA_11,
+. BFD_RELOC_HPPA_14,
+. BFD_RELOC_HPPA_17,
+.
+. BFD_RELOC_HPPA_L21,
+. BFD_RELOC_HPPA_R11,
+. BFD_RELOC_HPPA_R14,
+. BFD_RELOC_HPPA_R17,
+. BFD_RELOC_HPPA_LS21,
+. BFD_RELOC_HPPA_RS11,
+. BFD_RELOC_HPPA_RS14,
+. BFD_RELOC_HPPA_RS17,
+. BFD_RELOC_HPPA_LD21,
+. BFD_RELOC_HPPA_RD11,
+. BFD_RELOC_HPPA_RD14,
+. BFD_RELOC_HPPA_RD17,
+. BFD_RELOC_HPPA_LR21,
+. BFD_RELOC_HPPA_RR14,
+. BFD_RELOC_HPPA_RR17,
+.
+. BFD_RELOC_HPPA_GOTOFF_11,
+. BFD_RELOC_HPPA_GOTOFF_14,
+. BFD_RELOC_HPPA_GOTOFF_L21,
+. BFD_RELOC_HPPA_GOTOFF_R11,
+. BFD_RELOC_HPPA_GOTOFF_R14,
+. BFD_RELOC_HPPA_GOTOFF_LS21,
+. BFD_RELOC_HPPA_GOTOFF_RS11,
+. BFD_RELOC_HPPA_GOTOFF_RS14,
+. BFD_RELOC_HPPA_GOTOFF_LD21,
+. BFD_RELOC_HPPA_GOTOFF_RD11,
+. BFD_RELOC_HPPA_GOTOFF_RD14,
+. BFD_RELOC_HPPA_GOTOFF_LR21,
+. BFD_RELOC_HPPA_GOTOFF_RR14,
+.
+. BFD_RELOC_HPPA_DLT_32,
+. BFD_RELOC_HPPA_DLT_11,
+. BFD_RELOC_HPPA_DLT_14,
+. BFD_RELOC_HPPA_DLT_L21,
+. BFD_RELOC_HPPA_DLT_R11,
+. BFD_RELOC_HPPA_DLT_R14,
+.
+. BFD_RELOC_HPPA_ABS_CALL_11,
+. BFD_RELOC_HPPA_ABS_CALL_14,
+. BFD_RELOC_HPPA_ABS_CALL_17,
+. BFD_RELOC_HPPA_ABS_CALL_L21,
+. BFD_RELOC_HPPA_ABS_CALL_R11,
+. BFD_RELOC_HPPA_ABS_CALL_R14,
+. BFD_RELOC_HPPA_ABS_CALL_R17,
+. BFD_RELOC_HPPA_ABS_CALL_LS21,
+. BFD_RELOC_HPPA_ABS_CALL_RS11,
+. BFD_RELOC_HPPA_ABS_CALL_RS14,
+. BFD_RELOC_HPPA_ABS_CALL_RS17,
+. BFD_RELOC_HPPA_ABS_CALL_LD21,
+. BFD_RELOC_HPPA_ABS_CALL_RD11,
+. BFD_RELOC_HPPA_ABS_CALL_RD14,
+. BFD_RELOC_HPPA_ABS_CALL_RD17,
+. BFD_RELOC_HPPA_ABS_CALL_LR21,
+. BFD_RELOC_HPPA_ABS_CALL_RR14,
+. BFD_RELOC_HPPA_ABS_CALL_RR17,
+.
+. BFD_RELOC_HPPA_PCREL_CALL_11,
+. BFD_RELOC_HPPA_PCREL_CALL_12,
+. BFD_RELOC_HPPA_PCREL_CALL_14,
+. BFD_RELOC_HPPA_PCREL_CALL_17,
+. BFD_RELOC_HPPA_PCREL_CALL_L21,
+. BFD_RELOC_HPPA_PCREL_CALL_R11,
+. BFD_RELOC_HPPA_PCREL_CALL_R14,
+. BFD_RELOC_HPPA_PCREL_CALL_R17,
+. BFD_RELOC_HPPA_PCREL_CALL_LS21,
+. BFD_RELOC_HPPA_PCREL_CALL_RS11,
+. BFD_RELOC_HPPA_PCREL_CALL_RS14,
+. BFD_RELOC_HPPA_PCREL_CALL_RS17,
+. BFD_RELOC_HPPA_PCREL_CALL_LD21,
+. BFD_RELOC_HPPA_PCREL_CALL_RD11,
+. BFD_RELOC_HPPA_PCREL_CALL_RD14,
+. BFD_RELOC_HPPA_PCREL_CALL_RD17,
+. BFD_RELOC_HPPA_PCREL_CALL_LR21,
+. BFD_RELOC_HPPA_PCREL_CALL_RR14,
+. BFD_RELOC_HPPA_PCREL_CALL_RR17,
+.
+. BFD_RELOC_HPPA_PLABEL_32,
+. BFD_RELOC_HPPA_PLABEL_11,
+. BFD_RELOC_HPPA_PLABEL_14,
+. BFD_RELOC_HPPA_PLABEL_L21,
+. BFD_RELOC_HPPA_PLABEL_R11,
+. BFD_RELOC_HPPA_PLABEL_R14,
+.
+. BFD_RELOC_HPPA_UNWIND_ENTRY,
+. BFD_RELOC_HPPA_UNWIND_ENTRIES,
+.
+. {* i386/elf relocations *}
+. BFD_RELOC_386_GOT32,
+. BFD_RELOC_386_PLT32,
+. BFD_RELOC_386_COPY,
+. BFD_RELOC_386_GLOB_DAT,
+. BFD_RELOC_386_JUMP_SLOT,
+. BFD_RELOC_386_RELATIVE,
+. BFD_RELOC_386_GOTOFF,
+. BFD_RELOC_386_GOTPC,
+.
+. {* this must be the highest numeric value *}
+. BFD_RELOC_UNUSED
+. } bfd_reloc_code_real_type;
+*/
+
+
+/*
+SECTION
+ bfd_reloc_type_lookup
+
+SYNOPSIS
+ CONST struct reloc_howto_struct *
+ bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);
+
+DESCRIPTION
+ This routine returns a pointer to a howto struct which when
+ invoked, will perform the supplied relocation on data from the
+ architecture noted.
+
+*/
+
+
+CONST struct reloc_howto_struct *
+DEFUN(bfd_reloc_type_lookup,(abfd, code),
+ bfd *abfd AND
+ bfd_reloc_code_real_type code)
+{
+ return BFD_SEND (abfd, reloc_type_lookup, (abfd, code));
+}
+
+static reloc_howto_type bfd_howto_32 =
+ HOWTO(0, 00,2,32,false,0,complain_overflow_bitfield,0,"VRT32", false,0xffffffff,0xffffffff,true);
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_default_reloc_type_lookup
+
+SYNOPSIS
+ CONST struct reloc_howto_struct *bfd_default_reloc_type_lookup
+ (bfd *abfd AND
+ bfd_reloc_code_real_type code);
+
+DESCRIPTION
+ Provides a default relocation lookup routine for any architecture.
+
+
+*/
+
+CONST struct reloc_howto_struct *
+DEFUN(bfd_default_reloc_type_lookup, (abfd, code),
+ bfd *abfd AND
+ bfd_reloc_code_real_type code)
+{
+ switch (code)
+ {
+ case BFD_RELOC_CTOR:
+ /* The type of reloc used in a ctor, which will be as wide as the
+ address - so either a 64, 32, or 16 bitter. */
+ switch (bfd_get_arch_info (abfd)->bits_per_address) {
+ case 64:
+ BFD_FAIL();
+ case 32:
+ return &bfd_howto_32;
+ case 16:
+ BFD_FAIL();
+ default:
+ BFD_FAIL();
+ }
+ default:
+ BFD_FAIL();
+ }
+ return (CONST struct reloc_howto_struct *)NULL;
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_generic_relax_section
+
+SYNOPSIS
+ boolean bfd_generic_relax_section
+ (bfd *abfd,
+ asection *section,
+ asymbol **symbols);
+
+DESCRIPTION
+ Provides default handling for relaxing for back ends which
+ don't do relaxing -- i.e., does nothing.
+*/
+
+boolean
+DEFUN(bfd_generic_relax_section,(abfd, section, symbols),
+ bfd *abfd AND
+ asection *section AND
+ asymbol **symbols)
+{
+
+ return false;
+
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_generic_get_relocated_section_contents
+
+SYNOPSIS
+ bfd_byte *
+ bfd_generic_get_relocated_section_contents (bfd *abfd,
+ struct bfd_seclet *seclet,
+ bfd_byte *data,
+ boolean relocateable);
+
+DESCRIPTION
+ Provides default handling of relocation effort for back ends
+ which can't be bothered to do it efficiently.
+
+*/
+
+bfd_byte *
+DEFUN(bfd_generic_get_relocated_section_contents,(abfd,
+ seclet,
+ data,
+ relocateable),
+ bfd *abfd AND
+ struct bfd_seclet *seclet AND
+ bfd_byte *data AND
+ boolean relocateable)
+{
+ extern bfd_error_vector_type bfd_error_vector;
+
+ /* Get enough memory to hold the stuff */
+ bfd *input_bfd = seclet->u.indirect.section->owner;
+ asection *input_section = seclet->u.indirect.section;
+
+
+
+ size_t reloc_size = bfd_get_reloc_upper_bound(input_bfd, input_section);
+ arelent **reloc_vector = (arelent **) alloca(reloc_size);
+
+ /* read in the section */
+ bfd_get_section_contents(input_bfd,
+ input_section,
+ data,
+ 0,
+ input_section->_raw_size);
+
+/* We're not relaxing the section, so just copy the size info */
+ input_section->_cooked_size = input_section->_raw_size;
+ input_section->reloc_done = true;
+
+
+ if (bfd_canonicalize_reloc(input_bfd,
+ input_section,
+ reloc_vector,
+ seclet->u.indirect.symbols) )
+ {
+ arelent **parent;
+ for (parent = reloc_vector; * parent != (arelent *)NULL;
+ parent++)
+ {
+ bfd_reloc_status_type r=
+ bfd_perform_relocation(input_bfd,
+ *parent,
+ data,
+ input_section,
+ relocateable ? abfd : (bfd *) NULL);
+
+ if (relocateable)
+ {
+ asection *os = input_section->output_section;
+
+ /* A partial link, so keep the relocs */
+ os->orelocation[os->reloc_count] = *parent;
+ os->reloc_count++;
+ }
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ case bfd_reloc_undefined:
+ bfd_error_vector.undefined_symbol(*parent, seclet);
+ break;
+ case bfd_reloc_dangerous:
+ bfd_error_vector.reloc_dangerous(*parent, seclet);
+ break;
+ case bfd_reloc_outofrange:
+ case bfd_reloc_overflow:
+ bfd_error_vector.reloc_value_truncated(*parent, seclet);
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ }
+ }
+ }
+
+
+ return data;
+
+
+}
diff --git a/gnu/usr.bin/gdb/bfd/seclet.c b/gnu/usr.bin/gdb/bfd/seclet.c
new file mode 100644
index 000000000000..5dcc59ab0ef8
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/seclet.c
@@ -0,0 +1,185 @@
+/* seclet.c
+ Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This module is part of BFD */
+
+
+/* The intention is that one day, all the code which uses sections
+ will change and use seclets instead - maybe seglet would have been
+ a better name..
+
+ Anyway, a seclet contains enough info to be able to describe an
+ area of output memory in one go.
+
+ The only description so far catered for is that of the
+ <<bfd_indirect_seclet>>, which is a select which points to a
+ <<section>> and the <<asymbols>> associated with the section, so
+ that relocation can be done when needed.
+
+ One day there will be more types - they will at least migrate from
+ the linker's data structures - also there could be extra stuff,
+ like a bss seclet, which descibes a lump of memory as containing
+ zeros compactly, without the horrible SEC_* flag cruft.
+
+
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "seclet.h"
+#include "coff/internal.h"
+
+/* Create a new seclet and attach it to a section. */
+
+bfd_seclet_type *
+DEFUN(bfd_new_seclet,(abfd, section),
+ bfd *abfd AND
+ asection *section)
+{
+ bfd_seclet_type *n = (bfd_seclet_type *)bfd_alloc(abfd, sizeof(bfd_seclet_type));
+ if (section->seclets_tail != (bfd_seclet_type *)NULL) {
+ section->seclets_tail->next = n;
+ }
+ else
+ {
+ section->seclets_head = n;
+ }
+ section->seclets_tail = n;
+
+ return n;
+}
+
+/* Given an indirect seclet which points to an input section, relocate
+ the contents of the seclet and put the data in its final
+ destination. */
+
+static boolean
+DEFUN(rel,(abfd, seclet, output_section, data, relocateable),
+ bfd *abfd AND
+ bfd_seclet_type *seclet AND
+ asection *output_section AND
+ PTR data AND
+ boolean relocateable)
+{
+ if ((output_section->flags & SEC_HAS_CONTENTS) != 0
+ && seclet->size)
+ {
+ data = (PTR) bfd_get_relocated_section_contents(abfd, seclet, data,
+ relocateable);
+ if(bfd_set_section_contents(abfd,
+ output_section,
+ data,
+ seclet->offset,
+ seclet->size) == false)
+ {
+ abort();
+ }
+ }
+ return true;
+}
+
+/* Put the contents of a seclet in its final destination. */
+
+static boolean
+DEFUN(seclet_dump_seclet,(abfd, seclet, section, data, relocateable),
+ bfd *abfd AND
+ bfd_seclet_type *seclet AND
+ asection *section AND
+ PTR data AND
+ boolean relocateable)
+{
+ switch (seclet->type)
+ {
+ case bfd_indirect_seclet:
+ /* The contents of this section come from another one somewhere
+ else */
+ return rel(abfd, seclet, section, data, relocateable);
+
+ case bfd_fill_seclet:
+ /* Fill in the section with us */
+ {
+ char *d = bfd_xmalloc(seclet->size);
+ unsigned int i;
+ for (i =0; i < seclet->size; i+=2) {
+ d[i] = seclet->u.fill.value >> 8;
+ }
+ for (i = 1; i < seclet->size; i+=2) {
+ d[i] = seclet->u.fill.value ;
+ }
+ /* Don't bother to fill in empty sections */
+ if (!(bfd_get_section_flags(abfd, section) & SEC_HAS_CONTENTS))
+ {
+ return true;
+ }
+ return bfd_set_section_contents(abfd, section, d, seclet->offset,
+ seclet->size);
+ }
+
+ default:
+ abort();
+ }
+
+ return true;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_generic_seclet_link
+
+SYNOPSIS
+ boolean bfd_generic_seclet_link
+ (bfd *abfd,
+ PTR data,
+ boolean relocateable);
+
+DESCRIPTION
+
+ The generic seclet linking routine. The caller should have
+ set up seclets for all the output sections. The DATA argument
+ should point to a memory area large enough to hold the largest
+ section. This function looks through the seclets and moves
+ the contents into the output sections. If RELOCATEABLE is
+ true, the orelocation fields of the output sections must
+ already be initialized.
+
+*/
+
+boolean
+DEFUN(bfd_generic_seclet_link,(abfd, data, relocateable),
+ bfd *abfd AND
+ PTR data AND
+ boolean relocateable)
+{
+ asection *o = abfd->sections;
+ while (o != (asection *)NULL)
+ {
+ bfd_seclet_type *p = o->seclets_head;
+ while (p != (bfd_seclet_type *)NULL)
+ {
+ if (seclet_dump_seclet(abfd, p, o, data, relocateable) == false)
+ return false;
+ p = p ->next;
+ }
+ o = o->next;
+ }
+
+ return true;
+}
diff --git a/gnu/usr.bin/gdb/bfd/seclet.h b/gnu/usr.bin/gdb/bfd/seclet.h
new file mode 100644
index 000000000000..de5fdff0bb14
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/seclet.h
@@ -0,0 +1,55 @@
+/* Definitions of little sections (seclets) for BFD.
+ Copyright 1992 Free Software Foundation, Inc.
+ Hacked by Steve Chamberlain of Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _SECLET_H
+#define _SECLET_H
+
+enum bfd_seclet_enum
+{
+ bfd_indirect_seclet,
+ bfd_fill_seclet
+};
+
+struct bfd_seclet
+{
+ struct bfd_seclet *next;
+ enum bfd_seclet_enum type;
+ unsigned int offset;
+ unsigned int size;
+ union
+ {
+ struct
+ {
+ asection *section;
+ asymbol **symbols;
+ } indirect;
+ struct {
+ int value;
+ } fill;
+ }
+ u;
+};
+
+typedef struct bfd_seclet bfd_seclet_type;
+
+bfd_seclet_type *
+bfd_new_seclet PARAMS ((bfd *, asection *));
+
+#endif
diff --git a/gnu/usr.bin/gdb/bfd/section.c b/gnu/usr.bin/gdb/bfd/section.c
new file mode 100644
index 000000000000..547c69e2cb84
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/section.c
@@ -0,0 +1,899 @@
+/* Object file "section" support for the BFD library.
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ Sections
+
+ Sections are supported in BFD in <<section.c>>.
+
+ The raw data contained within a BFD is maintained through the
+ section abstraction. A single BFD may have any number of
+ sections, and keeps hold of them by pointing to the first,
+ each one points to the next in the list.
+
+@menu
+@* Section Input::
+@* Section Output::
+@* typedef asection::
+@* section prototypes::
+@end menu
+
+INODE
+Section Input, Section Output, Sections, Sections
+SUBSECTION
+ Section Input
+
+ When a BFD is opened for reading, the section structures are
+ created and attached to the BFD.
+
+ Each section has a name which describes the section in the
+ outside world - for example, <<a.out>> would contain at least
+ three sections, called <<.text>>, <<.data>> and <<.bss>>.
+
+ Names need not be unique; for example a COFF file may have several
+ sections named .data.
+
+ Sometimes a BFD will contain more than the 'natural' number of
+ sections. A back end may attach other sections containing
+ constructor data, or an application may add a section (using
+ bfd_make_section) to the sections attached to an already open
+ BFD. For example, the linker creates a supernumary section
+ <<COMMON>> for each input file's BFD to hold information about
+ common storage.
+
+ The raw data is not necessarily read in at the same time as
+ the section descriptor is created. Some targets may leave the
+ data in place until a <<bfd_get_section_contents>> call is
+ made. Other back ends may read in all the data at once - For
+ example; an S-record file has to be read once to determine the
+ size of the data. An IEEE-695 file doesn't contain raw data in
+ sections, but data and relocation expressions intermixed, so
+ the data area has to be parsed to get out the data and
+ relocations.
+
+INODE
+Section Output, typedef asection, Section Input, Sections
+
+SUBSECTION
+ Section Output
+
+ To write a new object style BFD, the various sections to be
+ written have to be created. They are attached to the BFD in
+ the same way as input sections, data is written to the
+ sections using <<bfd_set_section_contents>>.
+
+ Any program that creates or combines sections (e.g., the assembler
+ and linker) must use the fields <<output_section>> and
+ <<output_offset>> to indicate the file sections to which each
+ section must be written. (If the section is being created from
+ scratch, <<output_section>> should probably point to the section
+ itself, and <<output_offset>> should probably be zero.)
+
+ The data to be written comes from input sections attached to
+ the output sections. The output section structure can be
+ considered a filter for the input section, the output section
+ determines the vma of the output data and the name, but the
+ input section determines the offset into the output section of
+ the data to be written.
+
+ E.g., to create a section "O", starting at 0x100, 0x123 long,
+ containing two subsections, "A" at offset 0x0 (ie at vma
+ 0x100) and "B" at offset 0x20 (ie at vma 0x120) the structures
+ would look like:
+
+| section name "A"
+| output_offset 0x00
+| size 0x20
+| output_section -----------> section name "O"
+| | vma 0x100
+| section name "B" | size 0x123
+| output_offset 0x20 |
+| size 0x103 |
+| output_section --------|
+
+
+SUBSECTION
+ Seglets
+
+ The data within a section is stored in a <<seglet>>. These
+ are much like the fixups in <<gas>>. The seglet abstraction
+ allows the a section to grow and shrink within itself.
+
+ A seglet knows how big it is, and which is the next seglet and
+ where the raw data for it is, and also points to a list of
+ relocations which apply to it.
+
+ The seglet is used by the linker to perform relaxing on final
+ code. The application creates code which is as big as
+ necessary to make it work without relaxing, and the user can
+ select whether to relax. Sometimes relaxing takes a lot of
+ time. The linker runs around the relocations to see if any
+ are attached to data which can be shrunk, if so it does it on
+ a seglet by seglet basis.
+
+*/
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+/*
+DOCDD
+INODE
+typedef asection, section prototypes, Section Output, Sections
+SUBSECTION
+ typedef asection
+
+ The shape of a section struct:
+
+CODE_FRAGMENT
+.
+.typedef struct sec
+.{
+. {* The name of the section, the name isn't a copy, the pointer is
+. the same as that passed to bfd_make_section. *}
+.
+. CONST char *name;
+.
+. {* Which section is it 0.nth *}
+.
+. int index;
+.
+. {* The next section in the list belonging to the BFD, or NULL. *}
+.
+. struct sec *next;
+.
+. {* The field flags contains attributes of the section. Some of
+. flags are read in from the object file, and some are
+. synthesized from other information. *}
+.
+. flagword flags;
+.
+.#define SEC_NO_FLAGS 0x000
+.
+. {* Tells the OS to allocate space for this section when loaded.
+. This would clear for a section containing debug information
+. only. *}
+.#define SEC_ALLOC 0x001
+.
+. {* Tells the OS to load the section from the file when loading.
+. This would be clear for a .bss section *}
+.#define SEC_LOAD 0x002
+.
+. {* The section contains data still to be relocated, so there will
+. be some relocation information too. *}
+.#define SEC_RELOC 0x004
+.
+.#if 0 {* Obsolete ? *}
+.#define SEC_BALIGN 0x008
+.#endif
+.
+. {* A signal to the OS that the section contains read only
+. data. *}
+.#define SEC_READONLY 0x010
+.
+. {* The section contains code only. *}
+.#define SEC_CODE 0x020
+.
+. {* The section contains data only. *}
+.#define SEC_DATA 0x040
+.
+. {* The section will reside in ROM. *}
+.#define SEC_ROM 0x080
+.
+. {* The section contains constructor information. This section
+. type is used by the linker to create lists of constructors and
+. destructors used by <<g++>>. When a back end sees a symbol
+. which should be used in a constructor list, it creates a new
+. section for the type of name (eg <<__CTOR_LIST__>>), attaches
+. the symbol to it and builds a relocation. To build the lists
+. of constructors, all the linker has to do is catenate all the
+. sections called <<__CTOR_LIST__>> and relocte the data
+. contained within - exactly the operations it would peform on
+. standard data. *}
+.#define SEC_CONSTRUCTOR 0x100
+.
+. {* The section is a constuctor, and should be placed at the
+. end of the text, data, or bss section(?). *}
+.#define SEC_CONSTRUCTOR_TEXT 0x1100
+.#define SEC_CONSTRUCTOR_DATA 0x2100
+.#define SEC_CONSTRUCTOR_BSS 0x3100
+.
+. {* The section has contents - a data section could be
+. <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>, a debug section could be
+. <<SEC_HAS_CONTENTS>> *}
+.#define SEC_HAS_CONTENTS 0x200
+.
+. {* An instruction to the linker not to output sections
+. containing this flag even if they have information which
+. would normally be written. *}
+.#define SEC_NEVER_LOAD 0x400
+.
+. {* The section is a shared library section. The linker must leave
+. these completely alone, as the vma and size are used when
+. the executable is loaded. *}
+.#define SEC_SHARED_LIBRARY 0x800
+.
+. {* The section is a common section (symbols may be defined
+. multiple times, the value of a symbol is the amount of
+. space it requires, and the largest symbol value is the one
+. used). Most targets have exactly one of these (which we
+. translate to bfd_com_section), but ECOFF has two. *}
+.#define SEC_IS_COMMON 0x8000
+.
+. {* The section contains only debugging information. For
+. example, this is set for ELF .debug and .stab sections.
+. strip tests this flag to see if a section can be
+. discarded. *}
+.#define SEC_DEBUGGING 0x10000
+.
+. {* End of section flags. *}
+.
+. {* The virtual memory address of the section - where it will be
+. at run time. The symbols are relocated against this. The
+. user_set_vma flag is maintained by bfd; if it's not set, the
+. backend can assign addresses (for example, in <<a.out>>, where
+. the default address for <<.data>> is dependent on the specific
+. target and various flags). *}
+.
+. bfd_vma vma;
+. boolean user_set_vma;
+.
+. {* The load address of the section - where it would be in a
+. rom image, really only used for writing section header
+. information. *}
+.
+. bfd_vma lma;
+.
+. {* The size of the section in bytes, as it will be output.
+. contains a value even if the section has no contents (eg, the
+. size of <<.bss>>). This will be filled in after relocation *}
+.
+. bfd_size_type _cooked_size;
+.
+. {* The size on disk of the section in bytes originally. Normally this
+. value is the same as the size, but if some relaxing has
+. been done, then this value will be bigger. *}
+.
+. bfd_size_type _raw_size;
+.
+. {* If this section is going to be output, then this value is the
+. offset into the output section of the first byte in the input
+. section. Eg, if this was going to start at the 100th byte in
+. the output section, this value would be 100. *}
+.
+. bfd_vma output_offset;
+.
+. {* The output section through which to map on output. *}
+.
+. struct sec *output_section;
+.
+. {* The alignment requirement of the section, as an exponent - eg
+. 3 aligns to 2^3 (or 8) *}
+.
+. unsigned int alignment_power;
+.
+. {* If an input section, a pointer to a vector of relocation
+. records for the data in this section. *}
+.
+. struct reloc_cache_entry *relocation;
+.
+. {* If an output section, a pointer to a vector of pointers to
+. relocation records for the data in this section. *}
+.
+. struct reloc_cache_entry **orelocation;
+.
+. {* The number of relocation records in one of the above *}
+.
+. unsigned reloc_count;
+.
+. {* Information below is back end specific - and not always used
+. or updated. *}
+.
+. {* File position of section data *}
+.
+. file_ptr filepos;
+.
+. {* File position of relocation info *}
+.
+. file_ptr rel_filepos;
+.
+. {* File position of line data *}
+.
+. file_ptr line_filepos;
+.
+. {* Pointer to data for applications *}
+.
+. PTR userdata;
+.
+. struct lang_output_section *otheruserdata;
+.
+. {* Attached line number information *}
+.
+. alent *lineno;
+.
+. {* Number of line number records *}
+.
+. unsigned int lineno_count;
+.
+. {* When a section is being output, this value changes as more
+. linenumbers are written out *}
+.
+. file_ptr moving_line_filepos;
+.
+. {* what the section number is in the target world *}
+.
+. int target_index;
+.
+. PTR used_by_bfd;
+.
+. {* If this is a constructor section then here is a list of the
+. relocations created to relocate items within it. *}
+.
+. struct relent_chain *constructor_chain;
+.
+. {* The BFD which owns the section. *}
+.
+. bfd *owner;
+.
+. boolean reloc_done;
+. {* A symbol which points at this section only *}
+. struct symbol_cache_entry *symbol;
+. struct symbol_cache_entry **symbol_ptr_ptr;
+.
+. struct bfd_seclet *seclets_head;
+. struct bfd_seclet *seclets_tail;
+.} asection ;
+.
+.
+. {* These sections are global, and are managed by BFD. The application
+. and target back end are not permitted to change the values in
+. these sections. *}
+.#define BFD_ABS_SECTION_NAME "*ABS*"
+.#define BFD_UND_SECTION_NAME "*UND*"
+.#define BFD_COM_SECTION_NAME "*COM*"
+.#define BFD_IND_SECTION_NAME "*IND*"
+.
+. {* the absolute section *}
+.extern asection bfd_abs_section;
+. {* Pointer to the undefined section *}
+.extern asection bfd_und_section;
+. {* Pointer to the common section *}
+.extern asection bfd_com_section;
+. {* Pointer to the indirect section *}
+.extern asection bfd_ind_section;
+.
+.extern struct symbol_cache_entry *bfd_abs_symbol;
+.extern struct symbol_cache_entry *bfd_com_symbol;
+.extern struct symbol_cache_entry *bfd_und_symbol;
+.extern struct symbol_cache_entry *bfd_ind_symbol;
+.#define bfd_get_section_size_before_reloc(section) \
+. (section->reloc_done ? (abort(),1): (section)->_raw_size)
+.#define bfd_get_section_size_after_reloc(section) \
+. ((section->reloc_done) ? (section)->_cooked_size: (abort(),1))
+*/
+
+/* These symbols are global, not specific to any BFD. Therefore, anything
+ that tries to change them is broken, and should be repaired. */
+static CONST asymbol global_syms[] = {
+ /* the_bfd, name, value, attr, section [, udata] */
+ { 0, BFD_COM_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_com_section },
+ { 0, BFD_UND_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_und_section },
+ { 0, BFD_ABS_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_abs_section },
+ { 0, BFD_IND_SECTION_NAME, 0, BSF_SECTION_SYM, &bfd_ind_section },
+};
+
+#define STD_SECTION(SEC, FLAGS, SYM, NAME, IDX) \
+ asymbol *SYM = (asymbol *) &global_syms[IDX]; \
+ asection SEC = { NAME, 0, 0, FLAGS, 0, 0, (boolean) 0, 0, 0, 0, &SEC,\
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (boolean) 0, \
+ (asymbol *) &global_syms[IDX], &SYM, }
+
+STD_SECTION (bfd_com_section, SEC_IS_COMMON, bfd_com_symbol, BFD_COM_SECTION_NAME, 0);
+STD_SECTION (bfd_und_section, 0, bfd_und_symbol, BFD_UND_SECTION_NAME, 1);
+STD_SECTION (bfd_abs_section, 0, bfd_abs_symbol, BFD_ABS_SECTION_NAME, 2);
+STD_SECTION (bfd_ind_section, 0, bfd_ind_symbol, BFD_IND_SECTION_NAME, 3);
+#undef STD_SECTION
+
+/*
+DOCDD
+INODE
+section prototypes, , typedef asection, Sections
+SUBSECTION
+ section prototypes
+
+These are the functions exported by the section handling part of
+<<libbfd>.
+*/
+
+/*
+FUNCTION
+ bfd_get_section_by_name
+
+SYNOPSIS
+ asection *bfd_get_section_by_name(bfd *abfd, CONST char *name);
+
+DESCRIPTION
+ Runs through the provided @var{abfd} and returns the one of the
+ <<asection>>s who's name matches that provided, otherwise NULL.
+ @xref{Sections}, for more information.
+
+ This should only be used in special cases; the normal way to process
+ all sections of a given name is to use bfd_map_over_sections and
+ strcmp on the name (or better yet, base it on the section flags
+ or something else) for each section.
+*/
+
+asection *
+DEFUN(bfd_get_section_by_name,(abfd, name),
+ bfd *abfd AND
+ CONST char *name)
+{
+ asection *sect;
+
+ for (sect = abfd->sections; sect != NULL; sect = sect->next)
+ if (!strcmp (sect->name, name)) return sect;
+ return NULL;
+}
+
+
+/*
+FUNCTION
+ bfd_make_section_old_way
+
+SYNOPSIS
+ asection *bfd_make_section_old_way(bfd *, CONST char *name);
+
+DESCRIPTION
+ This function creates a new empty section called @var{name}
+ and attaches it to the end of the chain of sections for the
+ BFD supplied. An attempt to create a section with a name which
+ is already in use, returns its pointer without changing the
+ section chain.
+
+ It has the funny name since this is the way it used to be
+ before is was rewritten...
+
+ Possible errors are:
+ o invalid_operation -
+ If output has already started for this BFD.
+ o no_memory -
+ If obstack alloc fails.
+
+*/
+
+
+asection *
+DEFUN(bfd_make_section_old_way,(abfd, name),
+ bfd *abfd AND
+ CONST char * name)
+{
+ asection *sec = bfd_get_section_by_name(abfd, name);
+ if (sec == (asection *)NULL)
+ {
+ sec = bfd_make_section(abfd, name);
+ }
+ return sec;
+}
+
+/*
+FUNCTION
+ bfd_make_section_anyway
+
+SYNOPSIS
+ asection *bfd_make_section_anyway(bfd *, CONST char *name);
+
+DESCRIPTION
+ Create a new empty section called @var{name} and attach it to the end of
+ the chain of sections for @var{abfd}. Create a new section even if there
+ is already a section with that name.
+
+ Returns NULL and sets bfd_error on error; possible errors are:
+ o invalid_operation - If output has already started for @var{abfd}.
+ o no_memory - If obstack alloc fails.
+*/
+
+sec_ptr
+bfd_make_section_anyway (abfd, name)
+ bfd *abfd;
+ CONST 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) {
+ prev = &sect->next;
+ sect = sect->next;
+ }
+
+ newsect = (asection *) bfd_zalloc(abfd, sizeof (asection));
+ if (newsect == NULL) {
+ bfd_error = no_memory;
+ return NULL;
+ }
+
+ newsect->name = name;
+ newsect->index = abfd->section_count++;
+ newsect->flags = SEC_NO_FLAGS;
+
+ newsect->userdata = 0;
+ newsect->next = (asection *)NULL;
+ newsect->relocation = (arelent *)NULL;
+ newsect->reloc_count = 0;
+ newsect->line_filepos =0;
+ newsect->owner = abfd;
+
+ /* Create a symbol whos only job is to point to this section. This is
+ useful for things like relocs which are relative to the base of a
+ section. */
+ newsect->symbol = bfd_make_empty_symbol(abfd);
+ newsect->symbol->name = name;
+ newsect->symbol->value = 0;
+ newsect->symbol->section = newsect;
+ newsect->symbol->flags = BSF_SECTION_SYM;
+
+ newsect->symbol_ptr_ptr = &newsect->symbol;
+
+ if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) {
+ free (newsect);
+ return NULL;
+ }
+
+ *prev = newsect;
+ return newsect;
+}
+
+/*
+FUNCTION
+ bfd_make_section
+
+SYNOPSIS
+ asection *bfd_make_section(bfd *, CONST char *name);
+
+DESCRIPTION
+ Like bfd_make_section_anyway, but return NULL (without setting
+ bfd_error) without changing the section chain if there is already a
+ section named @var{name}. If there is an error, return NULL and set
+ bfd_error.
+*/
+
+sec_ptr
+DEFUN(bfd_make_section,(abfd, name),
+ bfd *abfd AND
+ CONST char * name)
+{
+ asection * sect = abfd->sections;
+
+ if (strcmp(name, BFD_ABS_SECTION_NAME) == 0)
+ {
+ return &bfd_abs_section;
+ }
+ if (strcmp(name, BFD_COM_SECTION_NAME) == 0)
+ {
+ return &bfd_com_section;
+ }
+ if (strcmp(name, BFD_UND_SECTION_NAME) == 0)
+ {
+ return &bfd_und_section;
+ }
+
+ if (strcmp(name, BFD_IND_SECTION_NAME) == 0)
+ {
+ return &bfd_ind_section;
+ }
+
+ while (sect) {
+ if (!strcmp(sect->name, name)) return NULL;
+ sect = sect->next;
+ }
+
+ /* The name is not already used; go ahead and make a new section. */
+ return bfd_make_section_anyway (abfd, name);
+}
+
+
+/*
+FUNCTION
+ bfd_set_section_flags
+
+SYNOPSIS
+ boolean bfd_set_section_flags(bfd *, asection *, flagword);
+
+DESCRIPTION
+ Attempts to set the attributes of the section named in the BFD
+ supplied to the value. Returns true on success, false on
+ error. Possible error returns are:
+
+ o invalid operation -
+ The section cannot have one or more of the attributes
+ requested. For example, a .bss section in <<a.out>> may not
+ have the <<SEC_HAS_CONTENTS>> field set.
+
+*/
+
+boolean
+DEFUN(bfd_set_section_flags,(abfd, section, flags),
+ bfd *abfd AND
+ sec_ptr section AND
+ flagword flags)
+{
+#if 0
+ /* If you try to copy a text section from an input file (where it
+ has the SEC_CODE flag set) to an output file, this loses big if
+ the bfd_applicable_section_flags (abfd) doesn't have the SEC_CODE
+ set - which it doesn't, at least not for a.out. FIXME */
+
+ if ((flags & bfd_applicable_section_flags (abfd)) != flags) {
+ bfd_error = invalid_operation;
+ return false;
+ }
+#endif
+
+ section->flags = flags;
+ return true;
+}
+
+
+/*
+FUNCTION
+ bfd_map_over_sections
+
+SYNOPSIS
+ void bfd_map_over_sections(bfd *abfd,
+ void (*func)(bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj);
+
+DESCRIPTION
+ Calls the provided function @var{func} for each section
+ attached to the BFD @var{abfd}, passing @var{obj} as an
+ argument. The function will be called as if by
+
+| func(abfd, the_section, obj);
+
+ This is the prefered method for iterating over sections, an
+ alternative would be to use a loop:
+
+| section *p;
+| for (p = abfd->sections; p != NULL; p = p->next)
+| func(abfd, p, ...)
+
+
+*/
+
+/*VARARGS2*/
+void
+DEFUN(bfd_map_over_sections,(abfd, operation, user_storage),
+ bfd *abfd AND
+ void (*operation) PARAMS ((bfd *abfd, asection *sect, PTR obj)) AND
+ PTR 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();
+}
+
+
+/*
+FUNCTION
+ bfd_set_section_size
+
+SYNOPSIS
+ boolean bfd_set_section_size(bfd *, asection *, bfd_size_type val);
+
+DESCRIPTION
+ Sets @var{section} to the size @var{val}. If the operation is
+ ok, then <<true>> is returned, else <<false>>.
+
+ Possible error returns:
+ o invalid_operation -
+ Writing has started to the BFD, so setting the size is invalid
+
+*/
+
+boolean
+DEFUN(bfd_set_section_size,(abfd, ptr, val),
+ bfd *abfd AND
+ sec_ptr ptr AND
+ bfd_size_type 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->_cooked_size = val;
+ ptr->_raw_size = val;
+
+ return true;
+}
+
+/*
+FUNCTION
+ bfd_set_section_contents
+
+SYNOPSIS
+ boolean bfd_set_section_contents
+ (bfd *abfd,
+ asection *section,
+ PTR data,
+ file_ptr offset,
+ bfd_size_type count);
+
+
+DESCRIPTION
+ Sets the contents of the section @var{section} in BFD
+ @var{abfd} to the data starting in memory at @var{data}. The
+ data is written to the output section starting at offset
+ @var{offset} for @var{count} bytes.
+
+
+
+ Normally <<true>> is returned, else <<false>>. Possible error
+ returns are:
+ o no_contents -
+ The output section does not have the <<SEC_HAS_CONTENTS>>
+ attribute, so nothing can be written to it.
+ o and some more too
+
+ This routine is front end to the back end function
+ <<_bfd_set_section_contents>>.
+
+
+*/
+
+#define bfd_get_section_size_now(abfd,sec) \
+(sec->reloc_done \
+ ? bfd_get_section_size_after_reloc (sec) \
+ : bfd_get_section_size_before_reloc (sec))
+
+boolean
+DEFUN(bfd_set_section_contents,(abfd, section, location, offset, count),
+ bfd *abfd AND
+ sec_ptr section AND
+ PTR location AND
+ file_ptr offset AND
+ bfd_size_type count)
+{
+ bfd_size_type sz;
+
+ if (!bfd_get_section_flags(abfd, section) & SEC_HAS_CONTENTS)
+ {
+ bfd_error = no_contents;
+ return(false);
+ }
+
+ if (offset < 0)
+ {
+ bad_val:
+ bfd_error = bad_value;
+ return false;
+ }
+ sz = bfd_get_section_size_now (abfd, section);
+ if (offset > sz
+ || count > sz
+ || offset + count > sz)
+ goto bad_val;
+
+ switch (abfd->direction)
+ {
+ case read_direction:
+ case no_direction:
+ bfd_error = invalid_operation;
+ return false;
+
+ case write_direction:
+ break;
+
+ case both_direction:
+ /* File is opened for update. `output_has_begun' some time ago when
+ the file was created. Do not recompute sections sizes or alignments
+ in _bfd_set_section_content. */
+ abfd->output_has_begun = true;
+ break;
+ }
+
+ if (BFD_SEND (abfd, _bfd_set_section_contents,
+ (abfd, section, location, offset, count)))
+ {
+ abfd->output_has_begun = true;
+ return true;
+ }
+
+ return false;
+}
+
+/*
+FUNCTION
+ bfd_get_section_contents
+
+SYNOPSIS
+ boolean bfd_get_section_contents
+ (bfd *abfd, asection *section, PTR location,
+ file_ptr offset, bfd_size_type count);
+
+DESCRIPTION
+ This function reads data from @var{section} in BFD @var{abfd}
+ into memory starting at @var{location}. The data is read at an
+ offset of @var{offset} from the start of the input section,
+ and is read for @var{count} bytes.
+
+ If the contents of a constuctor with the <<SEC_CONSTUCTOR>>
+ flag set are requested, then the @var{location} is filled with
+ zeroes. If no errors occur, <<true>> is returned, else
+ <<false>>.
+
+
+
+*/
+boolean
+DEFUN(bfd_get_section_contents,(abfd, section, location, offset, count),
+ bfd *abfd AND
+ sec_ptr section AND
+ PTR location AND
+ file_ptr offset AND
+ bfd_size_type count)
+{
+ bfd_size_type sz;
+
+ if (section->flags & SEC_CONSTRUCTOR)
+ {
+ memset(location, 0, (unsigned)count);
+ return true;
+ }
+
+ if (offset < 0)
+ {
+ bad_val:
+ bfd_error = bad_value;
+ return false;
+ }
+ sz = bfd_get_section_size_now (abfd, section);
+ if (offset > sz
+ || count > sz
+ || offset + count > sz)
+ goto bad_val;
+
+ if (count == 0)
+ /* Don't bother. */
+ return true;
+
+ return BFD_SEND (abfd, _bfd_get_section_contents,
+ (abfd, section, location, offset, count));
+}
diff --git a/gnu/usr.bin/gdb/bfd/srec.c b/gnu/usr.bin/gdb/bfd/srec.c
new file mode 100644
index 000000000000..88ba9570e34e
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/srec.c
@@ -0,0 +1,1001 @@
+/* BFD back-end for s-record objects.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SUBSECTION
+ S-Record handling
+
+DESCRIPTION
+
+ Ordinary S-Records cannot hold anything but addresses and
+ data, so that's all that we implement.
+
+ The only interesting thing is that S-Records 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
+ arbitrarily 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 bfd_alloc'd
+ area.
+
+ Any number of sections may be created for output, we save them
+ up and output them when it's time to close the bfd.
+
+ An s record looks like:
+
+EXAMPLE
+ S<type><length><address><data><checksum>
+
+DESCRIPTION
+ Where
+ o length
+ is the number of bytes following upto the checksum. Note that
+ this is not the number of chars following, since it takes two
+ chars to represent a byte.
+ o type
+ is one of:
+ 0) header record
+ 1) two byte address data record
+ 2) three byte address data record
+ 3) four byte address data record
+ 7) four byte address termination record
+ 8) three byte address termination record
+ 9) two byte address termination record
+
+ o address
+ is the start address of the data following, or in the case of
+ a termination record, the start address of the image
+ o data
+ is the data.
+ o checksum
+ is the sum of all the raw byte data in the record, from the length
+ upwards, modulo 256 and subtracted from 255.
+
+
+SUBSECTION
+ Symbol S-Record handling
+
+DESCRIPTION
+ Some ICE equipment understands an addition to the standard
+ S-Record format; symbols and their addresses can be sent
+ before the data.
+
+ The format of this is:
+ ($$ <modulename>
+ (<space> <symbol> <address>)*)
+ $$
+
+ so a short symbol table could look like:
+
+EXAMPLE
+ $$ flash.x
+ $$ flash.c
+ _port6 $0
+ _delay $4
+ _start $14
+ _etext $8036
+ _edata $8036
+ _end $8036
+ $$
+
+DESCRIPTION
+ We allow symbols to be anywhere in the data stream - the module names
+ are always ignored.
+
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* Macros for converting between hex and binary */
+
+static CONST char digs[] = "0123456789ABCDEF";
+
+static char hex_value[1 + (unsigned char)~0];
+
+#define NOT_HEX 20
+#define NIBBLE(x) hex_value[(unsigned char)(x)]
+#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
+#define TOHEX(d, x, ch) \
+ d[1] = digs[(x) & 0xf]; \
+ d[0] = digs[((x)>>4)&0xf]; \
+ ch += ((x) & 0xff);
+#define ISHEX(x) (hex_value[(unsigned char)(x)] != NOT_HEX)
+
+
+
+static void
+DEFUN_VOID(srec_init)
+{
+ unsigned int i;
+ static boolean inited = false;
+
+ if (inited == false)
+ {
+
+ inited = true;
+
+ for (i = 0; i < sizeof (hex_value); i++)
+ {
+ hex_value[i] = NOT_HEX;
+ }
+
+ for (i = 0; i < 10; i++)
+ {
+ hex_value[i + '0'] = i;
+
+ }
+ for (i = 0; i < 6; i++)
+ {
+ hex_value[i + 'a'] = i+10;
+ hex_value[i + 'A'] = i+10;
+ }
+ }
+}
+
+
+/* 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 21
+
+/* We cannot output our srecords as we see them, we have to glue them
+ together, this is done in this structure : */
+
+struct srec_data_list_struct
+{
+ unsigned char *data;
+ bfd_vma where;
+ bfd_size_type size;
+ struct srec_data_list_struct *next;
+
+
+} ;
+typedef struct srec_data_list_struct srec_data_list_type;
+
+
+typedef struct srec_data_struct
+{
+ srec_data_list_type *head;
+ unsigned int type;
+
+ int done_symbol_read;
+ int count;
+ asymbol *symbols;
+ char *strings;
+ int symbol_idx;
+ int string_size;
+ int string_idx;
+} tdata_type;
+
+
+/*
+ called once per input S-Record, used to work out vma and size of data.
+ */
+
+static bfd_vma low,high;
+
+static void
+size_symbols(abfd, buf, len, val)
+bfd *abfd;
+char *buf;
+int len;
+int val;
+{
+ abfd->symcount ++;
+ abfd->tdata.srec_data->string_size += len + 1;
+}
+
+static void
+fillup_symbols(abfd, buf, len, val)
+bfd *abfd;
+char *buf;
+int len;
+int val;
+{
+ if (!abfd->tdata.srec_data->done_symbol_read)
+ {
+ asymbol *p;
+ if (abfd->tdata.srec_data->symbols == 0)
+ {
+ abfd->tdata.srec_data->symbols = (asymbol *)bfd_alloc(abfd, abfd->symcount * sizeof(asymbol));
+ abfd->tdata.srec_data->strings = (char*)bfd_alloc(abfd, abfd->tdata.srec_data->string_size);
+ abfd->tdata.srec_data->symbol_idx = 0;
+ abfd->tdata.srec_data->string_idx = 0;
+ }
+
+ p = abfd->tdata.srec_data->symbols + abfd->tdata.srec_data->symbol_idx++;
+ p->the_bfd = abfd;
+ p->name = abfd->tdata.srec_data->strings + abfd->tdata.srec_data->string_idx;
+ memcpy((char *)(p->name), buf, len+1);
+ abfd->tdata.srec_data->string_idx += len + 1;
+ p->value = val;
+ p->flags = BSF_EXPORT | BSF_GLOBAL;
+ p->section = &bfd_abs_section;
+ p->udata = 0;
+ }
+}
+static void
+DEFUN(size_srec,(abfd, section, address, raw, length),
+ bfd *abfd AND
+ asection *section AND
+ bfd_vma address AND
+ bfd_byte *raw AND
+ unsigned int length)
+{
+ if (address < low)
+ low = address;
+ if (address + length > high)
+ high = address + length -1;
+}
+
+
+/*
+ called once per input S-Record, copies data from input into bfd_alloc'd area
+ */
+
+static void
+DEFUN(fillup,(abfd, section, address, raw, length),
+bfd *abfd AND
+asection *section AND
+bfd_vma address AND
+bfd_byte *raw AND
+unsigned int length)
+{
+ unsigned int i;
+ bfd_byte *dst =
+ (bfd_byte *)(section->used_by_bfd) + address - section->vma;
+ /* length -1 because we don't read in the checksum */
+ for (i = 0; i < length -1 ; i++) {
+ *dst = HEX(raw);
+ dst++;
+ raw+=2;
+ }
+}
+
+/* Pass over an S-Record file, calling one of the above functions on each
+ record. */
+
+static int white(x)
+char x;
+{
+return (x== ' ' || x == '\t' || x == '\n' || x == '\r');
+}
+static int
+skipwhite(src,abfd)
+char *src;
+bfd *abfd;
+{
+ int eof = 0;
+ while (white(*src) && !eof)
+ {
+ eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
+ }
+ return eof;
+}
+
+static boolean
+DEFUN(srec_mkobject, (abfd),
+ bfd *abfd)
+{
+ if (abfd->tdata.srec_data == 0)
+ {
+ tdata_type *tdata = (tdata_type *)bfd_alloc(abfd, sizeof(tdata_type));
+ abfd->tdata.srec_data = tdata;
+ tdata->type = 1;
+ tdata->head = (srec_data_list_type *)NULL;
+ }
+ return true;
+
+}
+
+static void
+DEFUN(pass_over,(abfd, func, symbolfunc, section),
+ bfd *abfd AND
+ void (*func)() AND
+ void (*symbolfunc)() AND
+ asection *section)
+{
+ unsigned int bytes_on_line;
+ boolean eof = false;
+
+ srec_mkobject(abfd);
+ /* To the front of the file */
+ bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+ while (eof == false)
+ {
+ char buffer[MAXCHUNK];
+ char *src = buffer;
+ char type;
+ bfd_vma address = 0;
+
+ /* Find first 'S' or $ */
+ eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
+ switch (*src)
+ {
+ default:
+ eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
+ if (eof) return;
+ break;
+
+ case '$':
+ /* Inside a symbol definition - just ignore the module name */
+ while (*src != '\n' && !eof)
+ {
+ eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
+ }
+ break;
+
+ case ' ':
+ /* spaces - maybe just before a symbol */
+ while (*src != '\n' && white(*src)) {
+ eof = skipwhite(src, abfd);
+
+{
+ int val = 0;
+ int slen = 0;
+ char symbol[MAXCHUNK];
+
+ /* get the symbol part */
+ while (!eof && !white(*src) && slen < MAXCHUNK)
+ {
+ symbol[slen++] = *src;
+ eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
+ }
+ symbol[slen] = 0;
+ eof = skipwhite(src, abfd);
+ /* skip the $ for the hex value */
+ if (*src == '$')
+ {
+ eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
+ }
+
+ /* Scan off the hex number */
+ while (isxdigit(*src ))
+ {
+ val *= 16;
+ if (isdigit(*src))
+ val += *src - '0';
+ else if (isupper(*src)) {
+ val += *src - 'A' + 10;
+ }
+ else {
+ val += *src - 'a' + 10;
+ }
+ eof = (boolean)(bfd_read(src, 1, 1, abfd) != 1);
+ }
+ symbolfunc(abfd, symbol, slen, val);
+ }
+}
+ break;
+ case 'S':
+ src++;
+
+ /* Fetch the type and the length */
+ bfd_read(src, 1, 3, abfd);
+
+ type = *src++;
+
+ if (!ISHEX (src[0]) || !ISHEX (src[1]))
+ break;
+
+ bytes_on_line = HEX(src);
+
+ if (bytes_on_line > MAXCHUNK/2)
+ break;
+ src+=2 ;
+
+ bfd_read(src, 1 , bytes_on_line * 2, abfd);
+
+ switch (type) {
+ case '0':
+ case '5':
+ /* Prologue - ignore */
+ break;
+ case '3':
+ address = HEX(src);
+ src+=2;
+ bytes_on_line--;
+
+ case '2':
+ address = HEX(src) | (address<<8) ;
+ src+=2;
+ bytes_on_line--;
+ case '1':
+ address = HEX(src) | (address<<8) ;
+ src+=2;
+ address = HEX(src) | (address<<8) ;
+ src+=2;
+ bytes_on_line-=2;
+ func(abfd,section, address, src, bytes_on_line);
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+}
+
+static bfd_target *
+object_p(abfd)
+bfd *abfd;
+{
+ asection *section;
+ /* We create one section called .text for all the contents,
+ and allocate enough room for the entire file. */
+
+ section = bfd_make_section(abfd, ".text");
+ section->_raw_size = 0;
+ section->vma = 0xffffffff;
+ low = 0xffffffff;
+ high = 0;
+ pass_over(abfd, size_srec, size_symbols, section);
+ section->_raw_size = high - low;
+ section->vma = low;
+ section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
+
+ if (abfd->symcount)
+ abfd->flags |= HAS_SYMS;
+ return abfd->xvec;
+}
+
+static bfd_target *
+DEFUN(srec_object_p, (abfd),
+ bfd *abfd)
+{
+ char b[4];
+
+ srec_init();
+
+ bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+ bfd_read(b, 1, 4, abfd);
+
+ if (b[0] != 'S' || !ISHEX(b[1]) || !ISHEX(b[2]) || !ISHEX(b[3]))
+ return (bfd_target*) NULL;
+
+ /* We create one section called .text for all the contents,
+ and allocate enough room for the entire file. */
+
+ return object_p(abfd);
+}
+
+
+static bfd_target *
+DEFUN(symbolsrec_object_p, (abfd),
+ bfd *abfd)
+{
+ char b[4];
+
+ srec_init();
+
+ bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+ bfd_read(b, 1, 4, abfd);
+
+ if (b[0] != '$' || b[1] != '$')
+ return (bfd_target*) NULL;
+
+ return object_p(abfd);
+}
+
+
+static boolean
+DEFUN(srec_get_section_contents,(abfd, section, location, offset, count),
+ bfd *abfd AND
+ asection *section AND
+ PTR location AND
+ file_ptr offset AND
+ bfd_size_type count)
+{
+ if (section->used_by_bfd == (PTR)NULL)
+ {
+ section->used_by_bfd = (PTR)bfd_alloc (abfd, section->_raw_size);
+
+ pass_over(abfd, fillup, fillup_symbols, section);
+ }
+ (void) memcpy((PTR)location,
+ (PTR)((char *)(section->used_by_bfd) + offset),
+ count);
+ return true;
+}
+
+
+
+boolean
+DEFUN(srec_set_arch_mach,(abfd, arch, machine),
+ bfd *abfd AND
+ enum bfd_architecture arch AND
+ unsigned long machine)
+{
+ return bfd_default_set_arch_mach(abfd, arch, machine);
+}
+
+
+/* we have to save up all the Srecords for a splurge before output,
+ also remember */
+
+static boolean
+DEFUN(srec_set_section_contents,(abfd, section, location, offset, bytes_to_do),
+ bfd *abfd AND
+ sec_ptr section AND
+ PTR location AND
+ file_ptr offset AND
+ bfd_size_type bytes_to_do)
+{
+ tdata_type *tdata = abfd->tdata.srec_data;
+ srec_data_list_type *entry = (srec_data_list_type *)
+ bfd_alloc(abfd, sizeof(srec_data_list_type));
+
+ if ((section->flags & SEC_ALLOC)
+ && (section->flags & SEC_LOAD))
+ {
+ unsigned char *data = (unsigned char *) bfd_alloc(abfd, bytes_to_do);
+ memcpy(data, location, bytes_to_do);
+
+ if ((section->lma + offset + bytes_to_do) <= 0xffff)
+ {
+
+ }
+ else if ((section->lma + offset + bytes_to_do) <= 0xffffff
+ && tdata->type < 2)
+ {
+ tdata->type = 2;
+ }
+ else
+ {
+ tdata->type = 3;
+ }
+
+ entry->data = data;
+ entry->where = section->lma + offset;
+ entry->size = bytes_to_do;
+ entry->next = tdata->head;
+ tdata->head = entry;
+ }
+ return true;
+}
+
+/* Write a record of type, of the supplied number of bytes. The
+ supplied bytes and length don't have a checksum. That's worked out
+ here
+*/
+static
+void DEFUN(srec_write_record,(abfd, type, address, data, end),
+ bfd *abfd AND
+ char type AND
+ bfd_vma address AND
+ CONST unsigned char *data AND
+ CONST unsigned char *end)
+
+{
+ char buffer[MAXCHUNK];
+
+ unsigned int check_sum = 0;
+ unsigned CONST char *src = data;
+ char *dst =buffer;
+ char *length;
+
+
+ *dst++ = 'S';
+ *dst++ = '0' + type;
+
+ length = dst;
+ dst+=2; /* leave room for dst*/
+
+ switch (type)
+ {
+ case 3:
+ case 7:
+ TOHEX(dst, (address >> 24), check_sum);
+ dst+=2;
+ case 8:
+ case 2:
+ TOHEX(dst, (address >> 16), check_sum);
+ dst+=2;
+ case 9:
+ case 1:
+ case 0:
+ TOHEX(dst, (address >> 8), check_sum);
+ dst+=2;
+ TOHEX(dst, (address), check_sum);
+ dst+=2;
+ break;
+
+ }
+ for (src = data; src < end; src++)
+ {
+ TOHEX(dst, *src, check_sum);
+ dst+=2;
+ }
+
+ /* Fill in the length */
+ TOHEX(length, (dst - length)/2, check_sum);
+ check_sum &= 0xff;
+ check_sum = 255 - check_sum;
+ TOHEX(dst, check_sum, check_sum);
+ dst+=2;
+
+ *dst ++ = '\r';
+ *dst ++ = '\n';
+ bfd_write((PTR)buffer, 1, dst - buffer , abfd);
+}
+
+
+
+static void
+DEFUN(srec_write_header,(abfd),
+ bfd *abfd)
+{
+ unsigned char buffer[MAXCHUNK];
+ unsigned char *dst = buffer;
+ unsigned int i;
+
+ /* I'll put an arbitary 40 char limit on header size */
+ for (i = 0; i < 40 && abfd->filename[i]; i++)
+ {
+ *dst++ = abfd->filename[i];
+ }
+ srec_write_record(abfd,0, 0, buffer, dst);
+}
+
+static void
+DEFUN(srec_write_section,(abfd, tdata, list),
+ bfd *abfd AND
+ tdata_type *tdata AND
+ srec_data_list_type *list)
+{
+ unsigned int bytes_written = 0;
+ unsigned char *location = list->data;
+
+ while (bytes_written < list->size)
+ {
+ bfd_vma address;
+
+ unsigned int bytes_this_chunk = list->size - bytes_written;
+
+ if (bytes_this_chunk > CHUNK)
+ {
+ bytes_this_chunk = CHUNK;
+ }
+
+ address = list->where + bytes_written;
+
+ srec_write_record(abfd,
+ tdata->type,
+ address,
+ location,
+ location + bytes_this_chunk);
+
+ bytes_written += bytes_this_chunk;
+ location += bytes_this_chunk;
+ }
+
+}
+
+static void
+DEFUN(srec_write_terminator,(abfd, tdata),
+ bfd *abfd AND
+ tdata_type *tdata)
+{
+ unsigned char buffer[2];
+
+ srec_write_record(abfd, 10 - tdata->type,
+ abfd->start_address, buffer, buffer);
+}
+
+
+
+static void
+srec_write_symbols(abfd)
+ bfd *abfd;
+{
+ char buffer[MAXCHUNK];
+ /* Dump out the symbols of a bfd */
+ int i;
+ int len = bfd_get_symcount(abfd);
+
+ if (len)
+ {
+ asymbol **table = bfd_get_outsymbols(abfd);
+ sprintf(buffer, "$$ %s\r\n", abfd->filename);
+
+ bfd_write(buffer, strlen(buffer), 1, abfd);
+
+ for (i = 0; i < len; i++)
+ {
+ asymbol *s = table[i];
+#if 0
+ int len = strlen(s->name);
+
+ /* If this symbol has a .[ocs] in it, it's probably a file name
+ and we'll output that as the module name */
+
+ if (len > 3 && s->name[len-2] == '.')
+ {
+ int l;
+ sprintf(buffer, "$$ %s\r\n", s->name);
+ l = strlen(buffer);
+ bfd_write(buffer, l, 1, abfd);
+ }
+ else
+#endif
+ if (s->flags & (BSF_GLOBAL | BSF_LOCAL)
+ && (s->flags & BSF_DEBUGGING) == 0
+ && s->name[0] != '.'
+ && s->name[0] != 't')
+ {
+ /* Just dump out non debug symbols */
+
+ int l;
+ char buf2[40], *p;
+
+ sprintf_vma (buf2, s->value + s->section->lma);
+ p = buf2;
+ while (p[0] == '0' && p[1] != 0)
+ p++;
+ sprintf (buffer, " %s $%s\r\n", s->name, p);
+ l = strlen(buffer);
+ bfd_write(buffer, l, 1,abfd);
+ }
+ }
+ sprintf(buffer, "$$ \r\n");
+ bfd_write(buffer, strlen(buffer), 1, abfd);
+ }
+}
+
+static boolean
+internal_srec_write_object_contents(abfd, symbols)
+ bfd *abfd;
+ int symbols;
+{
+ int bytes_written;
+ tdata_type *tdata = abfd->tdata.srec_data;
+ srec_data_list_type *list;
+
+ bytes_written = 0;
+
+
+ if (symbols)
+ srec_write_symbols(abfd);
+
+ srec_write_header(abfd);
+
+ /* Now wander though all the sections provided and output them */
+ list = tdata->head;
+
+ while (list != (srec_data_list_type*)NULL)
+ {
+ srec_write_section(abfd, tdata, list);
+ list = list->next;
+ }
+ srec_write_terminator(abfd, tdata);
+ return true;
+}
+
+static boolean
+srec_write_object_contents(abfd)
+ bfd *abfd;
+{
+ return internal_srec_write_object_contents(abfd, 0);
+}
+
+static boolean
+symbolsrec_write_object_contents(abfd)
+ bfd *abfd;
+{
+ return internal_srec_write_object_contents(abfd, 1);
+}
+
+static int
+DEFUN(srec_sizeof_headers,(abfd, exec),
+ bfd *abfd AND
+ boolean exec)
+{
+return 0;
+}
+
+static asymbol *
+DEFUN(srec_make_empty_symbol, (abfd),
+ bfd*abfd)
+{
+ asymbol *new= (asymbol *)bfd_zalloc (abfd, sizeof (asymbol));
+ new->the_bfd = abfd;
+ return new;
+}
+
+static unsigned int
+srec_get_symtab_upper_bound(abfd)
+bfd *abfd;
+{
+ /* Read in all the info */
+ srec_get_section_contents(abfd,abfd->sections,0,0,0);
+ return (bfd_get_symcount(abfd) + 1) * (sizeof(asymbol *));
+}
+
+static unsigned int
+DEFUN(srec_get_symtab, (abfd, alocation),
+ bfd *abfd AND
+ asymbol **alocation)
+{
+ int lim = abfd->symcount;
+ int i;
+ for (i = 0; i < lim; i++) {
+ alocation[i] = abfd->tdata.srec_data->symbols + i;
+ }
+ alocation[i] = 0;
+ return lim;
+}
+
+void
+DEFUN(srec_get_symbol_info,(ignore_abfd, symbol, ret),
+ bfd *ignore_abfd AND
+ asymbol *symbol AND
+ symbol_info *ret)
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+void
+DEFUN(srec_print_symbol,(ignore_abfd, afile, symbol, how),
+ bfd *ignore_abfd AND
+ PTR afile AND
+ asymbol *symbol AND
+ bfd_print_symbol_type how)
+{
+ FILE *file = (FILE *)afile;
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ fprintf (file, "%s", symbol->name);
+ break;
+ default:
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+ fprintf (file, " %-5s %s",
+ symbol->section->name,
+ symbol->name);
+
+ }
+}
+
+#define FOO PROTO
+#define srec_new_section_hook (FOO(boolean, (*), (bfd *, asection *)))bfd_true
+
+#define srec_get_reloc_upper_bound (FOO(unsigned int, (*),(bfd*, asection *)))bfd_false
+#define srec_canonicalize_reloc (FOO(unsigned int, (*),(bfd*,asection *, arelent **, asymbol **))) bfd_0
+
+
+
+#define srec_openr_next_archived_file (FOO(bfd *, (*), (bfd*,bfd*))) bfd_nullvoidptr
+#define srec_find_nearest_line (FOO(boolean, (*),(bfd*,asection*,asymbol**,bfd_vma, CONST char**, CONST char**, unsigned int *))) bfd_false
+#define srec_generic_stat_arch_elt (FOO(int, (*), (bfd *,struct stat *))) bfd_0
+
+
+#define srec_core_file_failing_command (char *(*)())(bfd_nullvoidptr)
+#define srec_core_file_failing_signal (int (*)())bfd_0
+#define srec_core_file_matches_executable_p (FOO(boolean, (*),(bfd*, bfd*)))bfd_false
+#define srec_slurp_armap bfd_true
+#define srec_slurp_extended_name_table bfd_true
+#define srec_truncate_arname (void (*)())bfd_nullvoidptr
+#define srec_write_armap (FOO( boolean, (*),(bfd *, unsigned int, struct orl *, unsigned int, int))) bfd_nullvoidptr
+#define srec_get_lineno (struct lineno_cache_entry *(*)())bfd_nullvoidptr
+#define srec_close_and_cleanup bfd_generic_close_and_cleanup
+#define srec_bfd_debug_info_start bfd_void
+#define srec_bfd_debug_info_end bfd_void
+#define srec_bfd_debug_info_accumulate (FOO(void, (*), (bfd *, asection *))) bfd_void
+#define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
+#define srec_bfd_relax_section bfd_generic_relax_section
+#define srec_bfd_seclet_link bfd_generic_seclet_link
+#define srec_bfd_reloc_type_lookup \
+ ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
+#define srec_bfd_make_debug_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+
+bfd_target srec_vec =
+{
+ "srec", /* name */
+ bfd_target_srec_flavour,
+ 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, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ 1, /* minimum alignment */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
+
+ {
+ _bfd_dummy_target,
+ srec_object_p, /* bfd_check_format */
+ (struct bfd_target *(*)()) bfd_nullvoidptr,
+ (struct bfd_target *(*)()) bfd_nullvoidptr,
+ },
+ {
+ bfd_false,
+ srec_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ srec_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+ JUMP_TABLE(srec)
+ };
+
+
+
+bfd_target symbolsrec_vec =
+{
+ "symbolsrec", /* name */
+ bfd_target_srec_flavour,
+ 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, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ 1, /* minimum alignment */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
+
+ {
+ _bfd_dummy_target,
+ symbolsrec_object_p, /* bfd_check_format */
+ (struct bfd_target *(*)()) bfd_nullvoidptr,
+ (struct bfd_target *(*)()) bfd_nullvoidptr,
+ },
+ {
+ bfd_false,
+ srec_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ symbolsrec_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+ JUMP_TABLE(srec),
+ (PTR) 0
+ };
+
diff --git a/gnu/usr.bin/gdb/bfd/stab-syms.c b/gnu/usr.bin/gdb/bfd/stab-syms.c
new file mode 100644
index 000000000000..88cf8506e47d
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/stab-syms.c
@@ -0,0 +1,59 @@
+/* Table of stab names for the BFD library.
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bfd.h"
+
+#define ARCH_SIZE 32 /* Value doesn't matter. */
+#include "libaout.h"
+#include "aout/aout64.h"
+
+/* Create a table of debugging stab-codes and corresponding names. */
+
+#define __define_name(CODE, STRING) {(int)CODE, STRING},
+#define __define_stab(NAME, CODE, STRING) __define_name(CODE, STRING)
+CONST struct {short code; char string[10];} aout_stab_names[]
+ = {
+#include "aout/stab.def"
+
+/* These are not really stab symbols, but it is
+ convenient to have them here for the sake of nm.
+ For completeness, we could also add N_TEXT etc, but those
+ are never needed, since nm treats those specially. */
+__define_name (N_SETA, "SETA") /* Absolute set element symbol */
+__define_name (N_SETT, "SETT") /* Text set element symbol */
+__define_name (N_SETD, "SETD") /* Data set element symbol */
+__define_name (N_SETB, "SETB") /* Bss set element symbol */
+__define_name (N_SETV, "SETV") /* Pointer to set vector in data area. */
+__define_name (N_INDR, "INDR")
+__define_name (N_WARNING, "WARNING")
+ };
+#undef __define_stab
+#undef GNU_EXTRA_STABS
+
+CONST char *
+DEFUN(aout_stab_name,(code),
+int code)
+{
+ register int i = sizeof(aout_stab_names) / sizeof(aout_stab_names[0]);
+ while (--i >= 0)
+ if (aout_stab_names[i].code == code)
+ return aout_stab_names[i].string;
+ return 0;
+}
diff --git a/gnu/usr.bin/gdb/bfd/syms.c b/gnu/usr.bin/gdb/bfd/syms.c
new file mode 100644
index 000000000000..89ac00124e3c
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/syms.c
@@ -0,0 +1,527 @@
+/* Generic symbol-table support for the BFD library.
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+SECTION
+ Symbols
+
+ BFD trys to maintain as much symbol information as it can when
+ it moves information from file to file. BFD passes information
+ to applications though the <<asymbol>> structure. When the
+ application requests the symbol table, BFD reads the table in
+ the native form and translates parts of it into the internal
+ format. To maintain more than the infomation passed to
+ applications some targets keep some information `behind the
+ scenes', in a structure only the particular back end knows
+ about. For example, the coff back end keeps the original
+ symbol table structure as well as the canonical structure when
+ a BFD is read in. On output, the coff back end can reconstruct
+ the output symbol table so that no information is lost, even
+ information unique to coff which BFD doesn't know or
+ understand. If a coff symbol table was read, but was written
+ through an a.out back end, all the coff specific information
+ would be lost. The symbol table of a BFD
+ is not necessarily read in until a canonicalize request is
+ made. Then the BFD back end fills in a table provided by the
+ application with pointers to the canonical information. To
+ output symbols, the application provides BFD with a table of
+ pointers to pointers to <<asymbol>>s. This allows applications
+ like the linker to output a symbol as read, since the `behind
+ the scenes' information will be still available.
+@menu
+@* Reading Symbols::
+@* Writing Symbols::
+@* typedef asymbol::
+@* symbol handling functions::
+@end menu
+
+INODE
+Reading Symbols, Writing Symbols, Symbols, Symbols
+SUBSECTION
+ Reading Symbols
+
+ There are two stages to reading a symbol table from a BFD;
+ allocating storage, and the actual reading process. This is an
+ excerpt from an appliction which reads the symbol table:
+
+| unsigned int storage_needed;
+| asymbol **symbol_table;
+| unsigned int number_of_symbols;
+| unsigned int i;
+|
+| storage_needed = get_symtab_upper_bound (abfd);
+|
+| if (storage_needed == 0) {
+| return ;
+| }
+| symbol_table = (asymbol **) bfd_xmalloc (storage_needed);
+| ...
+| number_of_symbols =
+| bfd_canonicalize_symtab (abfd, symbol_table);
+|
+| for (i = 0; i < number_of_symbols; i++) {
+| process_symbol (symbol_table[i]);
+| }
+
+ All storage for the symbols themselves is in an obstack
+ connected to the BFD, and is freed when the BFD is closed.
+
+
+INODE
+Writing Symbols, typedef asymbol, Reading Symbols, Symbols
+SUBSECTION
+ Writing Symbols
+
+ Writing of a symbol table is automatic when a BFD open for
+ writing is closed. The application attaches a vector of
+ pointers to pointers to symbols to the BFD being written, and
+ fills in the symbol count. The close and cleanup code reads
+ through the table provided and performs all the necessary
+ operations. The outputing code must always be provided with an
+ 'owned' symbol; one which has come from another BFD, or one
+ which has been created using <<bfd_make_empty_symbol>>. An
+ example showing the creation of a symbol table with only one element:
+
+| #include "bfd.h"
+| main()
+| {
+| bfd *abfd;
+| asymbol *ptrs[2];
+| asymbol *new;
+|
+| abfd = bfd_openw("foo","a.out-sunos-big");
+| bfd_set_format(abfd, bfd_object);
+| new = bfd_make_empty_symbol(abfd);
+| new->name = "dummy_symbol";
+| new->section = bfd_make_section_old_way(abfd, ".text");
+| new->flags = BSF_GLOBAL;
+| new->value = 0x12345;
+|
+| ptrs[0] = new;
+| ptrs[1] = (asymbol *)0;
+|
+| bfd_set_symtab(abfd, ptrs, 1);
+| bfd_close(abfd);
+| }
+|
+| ./makesym
+| nm foo
+| 00012345 A dummy_symbol
+
+ Many formats cannot represent arbitary symbol information; for
+ instance the <<a.out>> object format does not allow an
+ arbitary number of sections. A symbol pointing to a section
+ which is not one of <<.text>>, <<.data>> or <<.bss>> cannot
+ be described.
+
+*/
+
+
+
+/*
+DOCDD
+INODE
+typedef asymbol, symbol handling functions, Writing Symbols, Symbols
+
+*/
+/*
+SUBSECTION
+ typedef asymbol
+
+ An <<asymbol>> has the form:
+
+*/
+
+/*
+CODE_FRAGMENT
+
+.
+.typedef struct symbol_cache_entry
+.{
+. {* A pointer to the BFD which owns the symbol. This information
+. is necessary so that a back end can work out what additional
+. information (invisible to the application writer) is carried
+. with the symbol.
+.
+. This field is *almost* redundant, since you can use section->owner
+. instead, except that some symbols point to the global sections
+. bfd_{abs,com,und}_section. This could be fixed by making
+. these globals be per-bfd (or per-target-flavor). FIXME. *}
+.
+. struct _bfd *the_bfd; {* Use bfd_asymbol_bfd(sym) to access this field. *}
+.
+. {* The text of the symbol. The name is left alone, and not copied - the
+. application may not alter it. *}
+. CONST char *name;
+.
+. {* The value of the symbol. This really should be a union of a
+. numeric value with a pointer, since some flags indicate that
+. a pointer to another symbol is stored here. *}
+. symvalue value;
+.
+. {* Attributes of a symbol: *}
+.
+.#define BSF_NO_FLAGS 0x00
+.
+. {* The symbol has local scope; <<static>> in <<C>>. The value
+. is the offset into the section of the data. *}
+.#define BSF_LOCAL 0x01
+.
+. {* The symbol has global scope; initialized data in <<C>>. The
+. value is the offset into the section of the data. *}
+.#define BSF_GLOBAL 0x02
+.
+. {* The symbol has global scope, and is exported. The value is
+. the offset into the section of the data. *}
+.#define BSF_EXPORT BSF_GLOBAL {* no real difference *}
+.
+. {* A normal C symbol would be one of:
+. <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+. <<BSF_GLOBAL>> *}
+.
+. {* The symbol is a debugging record. The value has an arbitary
+. meaning. *}
+.#define BSF_DEBUGGING 0x08
+.
+. {* The symbol denotes a function entry point. Used in ELF,
+. perhaps others someday. *}
+.#define BSF_FUNCTION 0x10
+.
+. {* Used by the linker. *}
+.#define BSF_KEEP 0x20
+.#define BSF_KEEP_G 0x40
+.
+. {* A weak global symbol, overridable without warnings by
+. a regular global symbol of the same name. *}
+.#define BSF_WEAK 0x80
+.
+. {* This symbol was created to point to a section, e.g. ELF's
+. STT_SECTION symbols. *}
+.#define BSF_SECTION_SYM 0x100
+.
+. {* The symbol used to be a common symbol, but now it is
+. allocated. *}
+.#define BSF_OLD_COMMON 0x200
+.
+. {* The default value for common data. *}
+.#define BFD_FORT_COMM_DEFAULT_VALUE 0
+.
+. {* In some files the type of a symbol sometimes alters its
+. location in an output file - ie in coff a <<ISFCN>> symbol
+. which is also <<C_EXT>> symbol appears where it was
+. declared and not at the end of a section. This bit is set
+. by the target BFD part to convey this information. *}
+.
+.#define BSF_NOT_AT_END 0x400
+.
+. {* Signal that the symbol is the label of constructor section. *}
+.#define BSF_CONSTRUCTOR 0x800
+.
+. {* Signal that the symbol is a warning symbol. If the symbol
+. is a warning symbol, then the value field (I know this is
+. tacky) will point to the asymbol which when referenced will
+. cause the warning. *}
+.#define BSF_WARNING 0x1000
+.
+. {* Signal that the symbol is indirect. The value of the symbol
+. is a pointer to an undefined asymbol which contains the
+. name to use instead. *}
+.#define BSF_INDIRECT 0x2000
+.
+. {* BSF_FILE marks symbols that contain a file name. This is used
+. for ELF STT_FILE symbols. *}
+.#define BSF_FILE 0x4000
+.
+. flagword flags;
+.
+. {* A pointer to the section to which this symbol is
+. relative. This will always be non NULL, there are special
+. sections for undefined and absolute symbols *}
+. struct sec *section;
+.
+. {* Back end special data. This is being phased out in favour
+. of making this a union. *}
+. PTR udata;
+.
+.} asymbol;
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#include "libbfd.h"
+#include "aout/stab_gnu.h"
+
+/*
+DOCDD
+INODE
+symbol handling functions, , typedef asymbol, Symbols
+SUBSECTION
+ Symbol Handling Functions
+*/
+
+/*
+FUNCTION
+ get_symtab_upper_bound
+
+DESCRIPTION
+ Returns the number of bytes required in a vector of pointers
+ to <<asymbols>> for all the symbols in the supplied BFD,
+ including a terminal NULL pointer. If there are no symbols in
+ the BFD, then 0 is returned.
+
+.#define get_symtab_upper_bound(abfd) \
+. BFD_SEND (abfd, _get_symtab_upper_bound, (abfd))
+
+*/
+
+/*
+FUNCTION
+ bfd_canonicalize_symtab
+
+DESCRIPTION
+ Supplied a BFD and a pointer to an uninitialized vector of
+ pointers. This reads in the symbols from the BFD, and fills in
+ the table with pointers to the symbols, and a trailing NULL.
+ The routine returns the actual number of symbol pointers not
+ including the NULL.
+
+
+.#define bfd_canonicalize_symtab(abfd, location) \
+. BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+. (abfd, location))
+
+*/
+
+
+/*
+FUNCTION
+ bfd_set_symtab
+
+DESCRIPTION
+ Provided a table of pointers to symbols and a count, writes to
+ the output BFD the symbols when closed.
+
+SYNOPSIS
+ boolean bfd_set_symtab (bfd *, asymbol **, unsigned int );
+*/
+
+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;
+}
+
+/*
+FUNCTION
+ bfd_print_symbol_vandf
+
+DESCRIPTION
+ Prints the value and flags of the symbol supplied to the stream file.
+
+SYNOPSIS
+ void bfd_print_symbol_vandf(PTR file, asymbol *symbol);
+*/
+void
+DEFUN(bfd_print_symbol_vandf,(file, symbol),
+PTR file AND
+asymbol *symbol)
+{
+ flagword type = symbol->flags;
+ if (symbol->section != (asection *)NULL)
+ {
+ fprintf_vma(file, symbol->value+symbol->section->vma);
+ }
+ else
+ {
+ fprintf_vma(file, symbol->value);
+ }
+ fprintf(file," %c%c%c%c%c%c%c",
+ (type & BSF_LOCAL) ? 'l':' ',
+ (type & BSF_GLOBAL) ? 'g' : ' ',
+ (type & BSF_WEAK) ? 'w' : ' ',
+ (type & BSF_CONSTRUCTOR) ? 'C' : ' ',
+ (type & BSF_WARNING) ? 'W' : ' ',
+ (type & BSF_INDIRECT) ? 'I' : ' ',
+ (type & BSF_DEBUGGING) ? 'd' :' ');
+
+}
+
+
+/*
+FUNCTION
+ bfd_make_empty_symbol
+
+DESCRIPTION
+ This function creates a new <<asymbol>> structure for the BFD,
+ and returns a pointer to it.
+
+ This routine is necessary, since each back end has private
+ information surrounding the <<asymbol>>. Building your own
+ <<asymbol>> and pointing to it will not create the private
+ information, and will cause problems later on.
+
+.#define bfd_make_empty_symbol(abfd) \
+. BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+*/
+
+/*
+FUNCTION
+ bfd_make_debug_symbol
+
+DESCRIPTION
+ This function creates a new <<asymbol>> structure for the BFD,
+ to be used as a debugging symbol. Further details of its use have
+ yet to be worked out.
+
+.#define bfd_make_debug_symbol(abfd,ptr,size) \
+. BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+*/
+
+struct section_to_type
+{
+ CONST char *section;
+ char type;
+};
+
+/* Map COFF section names to POSIX/BSD single-character symbol types.
+ This table is probably incomplete. It is sorted for convenience of
+ adding entries. Since it is so short, a linear search is used. */
+static CONST struct section_to_type stt[] = {
+ {"*DEBUG*", 'N'},
+ {".bss", 'b'},
+ {".data", 'd'},
+ {".sbss", 's'}, /* Small BSS (uninitialized data) */
+ {".scommon", 'c'}, /* Small common */
+ {".sdata", 'g'}, /* Small initialized data */
+ {".text", 't'},
+ {0, 0}
+};
+
+/* Return the single-character symbol type corresponding to
+ COFF section S, or '?' for an unknown COFF section. */
+
+static char
+coff_section_type (s)
+ char *s;
+{
+ CONST struct section_to_type *t;
+
+ for (t = &stt[0]; t->section; t++)
+ if (!strcmp (s, t->section))
+ return t->type;
+ return '?';
+}
+
+#ifndef islower
+#define islower(c) ((c) >= 'a' && (c) <= 'z')
+#endif
+#ifndef toupper
+#define toupper(c) (islower(c) ? ((c) & ~0x20) : (c))
+#endif
+
+/*
+FUNCTION
+ bfd_decode_symclass
+
+DESCRIPTION
+ Return a character corresponding to the symbol
+ class of symbol, or '?' for an unknown class.
+
+SYNOPSIS
+ int bfd_decode_symclass(asymbol *symbol);
+*/
+int
+DEFUN(bfd_decode_symclass,(symbol),
+asymbol *symbol)
+{
+ char c;
+
+ if (bfd_is_com_section (symbol->section))
+ return 'C';
+ if (symbol->section == &bfd_und_section)
+ return 'U';
+ if (symbol->section == &bfd_ind_section)
+ return 'I';
+ if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
+ return '?';
+
+ if (symbol->section == &bfd_abs_section)
+ c = 'a';
+ else if (symbol->section)
+ c = coff_section_type (symbol->section->name);
+ else
+ return '?';
+ if (symbol->flags & BSF_GLOBAL)
+ c = toupper (c);
+ return c;
+
+ /* 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';
+ */
+}
+
+/*
+FUNCTION
+ bfd_symbol_info
+
+DESCRIPTION
+ Fill in the basic info about symbol that nm needs.
+ Additional info may be added by the back-ends after
+ calling this function.
+
+SYNOPSIS
+ void bfd_symbol_info(asymbol *symbol, symbol_info *ret);
+*/
+
+void
+DEFUN(bfd_symbol_info,(symbol, ret),
+ asymbol *symbol AND
+ symbol_info *ret)
+{
+ ret->type = bfd_decode_symclass (symbol);
+ if (ret->type != 'U')
+ ret->value = symbol->value+symbol->section->vma;
+ else
+ ret->value = 0;
+ ret->name = symbol->name;
+}
+
+void
+bfd_symbol_is_absolute()
+{
+ abort();
+}
+
diff --git a/gnu/usr.bin/gdb/bfd/sysdep.h b/gnu/usr.bin/gdb/bfd/sysdep.h
new file mode 100644
index 000000000000..dd7328b1d0f0
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/sysdep.h
@@ -0,0 +1,47 @@
+#ifndef hosts_i386bsd_H
+/* Intel 386 running any BSD Unix */
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/file.h>
+#include <machine/param.h>
+#include <machine/vmparam.h>
+
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+
+#define SEEK_SET 0
+#define SEEK_CUR 1
+
+#define HOST_PAGE_SIZE NBPG
+#define HOST_MACHINE_ARCH bfd_arch_i386
+#define HOST_TEXT_START_ADDR USRTEXT
+
+/* Jolitz suggested defining HOST_STACK_END_ADDR to
+ (u.u_kproc.kp_eproc.e_vm.vm_maxsaddr + MAXSSIZ), which should work on
+ both BSDI and 386BSD, but that is believed not to work for BSD 4.4. */
+
+#ifdef __bsdi__
+/* This seems to be the right thing for BSDI. */
+#define HOST_STACK_END_ADDR USRSTACK
+#else
+/* This seems to be the right thing for 386BSD release 0.1. */
+#define HOST_STACK_END_ADDR (USRSTACK - MAXSSIZ)
+#endif
+
+#define HOST_DATA_START_ADDR ((bfd_vma)u.u_kproc.kp_eproc.e_vm.vm_daddr)
+
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(core_bfd) \
+ ((core_bfd)->tdata.trad_core_data->u.u_sig)
+#define u_comm u_kproc.kp_proc.p_comm
+
+#include "fopen-same.h"
+
+#define hosts_i386bsd_H
+#endif
diff --git a/gnu/usr.bin/gdb/bfd/targets.c b/gnu/usr.bin/gdb/bfd/targets.c
new file mode 100644
index 000000000000..d6a966588c45
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/targets.c
@@ -0,0 +1,635 @@
+/* Generic target-file-type support for the BFD library.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/*
+SECTION
+ Targets
+
+DESCRIPTION
+ Each port of BFD to a different machine requries the creation
+ of a target back end. All the back end provides to the root
+ part of BFD is a structure containing pointers to functions
+ which perform certain low level operations on files. BFD
+ translates the applications's requests through a pointer into
+ calls to the back end routines.
+
+ When a file is opened with <<bfd_openr>>, its format and
+ target are unknown. BFD uses various mechanisms to determine
+ how to interpret the file. The operations performed are:
+
+ o First a BFD is created by calling the internal routine
+ <<new_bfd>>, then <<bfd_find_target>> is called with the
+ target string supplied to <<bfd_openr>> and the new BFD pointer.
+
+ o If a null target string was provided to <<bfd_find_target>>,
+ it looks up the environment variable <<GNUTARGET>> and uses
+ that as the target string.
+
+ o If the target string is still NULL, or the target string is
+ <<default>>, then the first item in the target vector is used
+ as the target type, and <<target_defaulted>> is set to
+ cause <<bfd_check_format>> to loop through all the targets.
+ @xref{bfd_target}. @xref{Formats}.
+
+ o Otherwise, the elements in the target vector are inspected
+ one by one, until a match on target name is found. When found,
+ that is used.
+
+ o Otherwise the error <<invalid_target>> is returned to
+ <<bfd_openr>>.
+
+ o <<bfd_openr>> attempts to open the file using
+ <<bfd_open_file>>, and returns the BFD.
+
+ Once the BFD has been opened and the target selected, the file
+ format may be determined. This is done by calling
+ <<bfd_check_format>> on the BFD with a suggested format.
+ If <<target_defaulted>> has been set, each possible target
+ type is tried to see if it recognizes the specified format. The
+ routine returns <<true>> when the application guesses right.
+@menu
+@* bfd_target::
+@end menu
+*/
+
+
+/*
+
+INODE
+ bfd_target, , Targets, Targets
+DOCDD
+SUBSECTION
+ bfd_target
+
+DESCRIPTION
+ This structure contains everything that BFD knows about a
+ target. It includes things like its byte order, name, what
+ routines to call to do various operations, etc.
+
+ Every BFD points to a target structure with its <<xvec>>
+ member.
+
+ These macros are used to dispatch to functions through the
+ bfd_target vector. They are used in a number of macros further
+ down in @file{bfd.h}, and are also used when calling various
+ routines by hand inside the BFD implementation. The "arglist"
+ argument must be parenthesized; it contains all the arguments
+ to the called function.
+
+ They make the documentation (more) unpleasant to read, so if
+ someone wants to fix this and not break the above, please do.
+
+.#define BFD_SEND(bfd, message, arglist) \
+. ((*((bfd)->xvec->message)) arglist)
+
+ For operations which index on the BFD format
+
+.#define BFD_SEND_FMT(bfd, message, arglist) \
+. (((bfd)->xvec->message[(int)((bfd)->format)]) arglist)
+
+ This is the struct which defines the type of BFD this is. The
+ <<xvec>> member of the struct <<bfd>> itself points here. Each
+ module that implements access to a different target under BFD,
+ defines one of these.
+
+
+ FIXME, these names should be rationalised with the names of
+ the entry points which call them. Too bad we can't have one
+ macro to define them both!
+
+.typedef struct bfd_target
+.{
+
+Identifies the kind of target, eg SunOS4, Ultrix, etc.
+
+. char *name;
+
+The "flavour" of a back end is a general indication about the contents
+of a file.
+
+. enum target_flavour {
+. bfd_target_unknown_flavour,
+. bfd_target_aout_flavour,
+. bfd_target_coff_flavour,
+. bfd_target_ecoff_flavour,
+. bfd_target_elf_flavour,
+. bfd_target_ieee_flavour,
+. bfd_target_nlm_flavour,
+. bfd_target_oasys_flavour,
+. bfd_target_tekhex_flavour,
+. bfd_target_srec_flavour,
+. bfd_target_hppa_flavour} flavour;
+
+The order of bytes within the data area of a file.
+
+. boolean byteorder_big_p;
+
+The order of bytes within the header parts of a file.
+
+. boolean header_byteorder_big_p;
+
+This is a mask of all the flags which an executable may have set -
+from the set <<NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>.
+
+. flagword object_flags;
+
+This is a mask of all the flags which a section may have set - from
+the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>.
+
+. flagword section_flags;
+
+The character normally found at the front of a symbol
+(if any), perhaps _.
+
+. char symbol_leading_char;
+
+The pad character for filenames within an archive header.
+
+. char ar_pad_char;
+
+The maximum number of characters in an archive header.
+
+. unsigned short ar_max_namelen;
+
+The minimum alignment restriction for any section.
+
+. unsigned int align_power_min;
+
+Entries for byte swapping for data. These are different to the other
+entry points, since they don't take BFD as first arg. Certain other handlers
+could do the same.
+
+. bfd_vma (*bfd_getx64) PARAMS ((bfd_byte *));
+. bfd_signed_vma (*bfd_getx_signed_64) PARAMS ((bfd_byte *));
+. void (*bfd_putx64) PARAMS ((bfd_vma, bfd_byte *));
+. bfd_vma (*bfd_getx32) PARAMS ((bfd_byte *));
+. bfd_signed_vma (*bfd_getx_signed_32) PARAMS ((bfd_byte *));
+. void (*bfd_putx32) PARAMS ((bfd_vma, bfd_byte *));
+. bfd_vma (*bfd_getx16) PARAMS ((bfd_byte *));
+. bfd_signed_vma (*bfd_getx_signed_16) PARAMS ((bfd_byte *));
+. void (*bfd_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+Byte swapping for the headers
+
+. bfd_vma (*bfd_h_getx64) PARAMS ((bfd_byte *));
+. bfd_signed_vma (*bfd_h_getx_signed_64) PARAMS ((bfd_byte *));
+. void (*bfd_h_putx64) PARAMS ((bfd_vma, bfd_byte *));
+. bfd_vma (*bfd_h_getx32) PARAMS ((bfd_byte *));
+. bfd_signed_vma (*bfd_h_getx_signed_32) PARAMS ((bfd_byte *));
+. void (*bfd_h_putx32) PARAMS ((bfd_vma, bfd_byte *));
+. bfd_vma (*bfd_h_getx16) PARAMS ((bfd_byte *));
+. bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((bfd_byte *));
+. void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+
+Format dependent routines: these are vectors of entry points
+within the target vector structure, one for each format to check.
+
+Check the format of a file being read. Return bfd_target * or zero.
+
+. struct bfd_target * (*_bfd_check_format[bfd_type_end]) PARAMS ((bfd *));
+
+Set the format of a file being written.
+
+. boolean (*_bfd_set_format[bfd_type_end]) PARAMS ((bfd *));
+
+Write cached information into a file being written, at bfd_close.
+
+. boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+The following functions are defined in <<JUMP_TABLE>>. The idea is
+that the back end writer of <<foo>> names all the routines
+<<foo_>>@var{entry_point}, <<JUMP_TABLE>> will built the entries
+in this structure in the right order.
+
+Core file entry points
+
+. char * (*_core_file_failing_command) PARAMS ((bfd *));
+. int (*_core_file_failing_signal) PARAMS ((bfd *));
+. boolean (*_core_file_matches_executable_p) PARAMS ((bfd *, bfd *));
+
+Archive entry points
+
+. boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+. boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+. void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *));
+. boolean (*write_armap) PARAMS ((bfd *arch,
+. unsigned int elength,
+. struct orl *map,
+. unsigned int orl_count,
+. int stridx));
+
+Standard stuff.
+
+. boolean (*_close_and_cleanup) PARAMS ((bfd *));
+. boolean (*_bfd_set_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+. file_ptr, bfd_size_type));
+. boolean (*_bfd_get_section_contents) PARAMS ((bfd *, sec_ptr, PTR,
+. file_ptr, bfd_size_type));
+. boolean (*_new_section_hook) PARAMS ((bfd *, sec_ptr));
+
+Symbols and relocations
+
+. unsigned int (*_get_symtab_upper_bound) PARAMS ((bfd *));
+. unsigned int (*_bfd_canonicalize_symtab) PARAMS ((bfd *,
+. struct symbol_cache_entry **));
+. unsigned int (*_get_reloc_upper_bound) PARAMS ((bfd *, sec_ptr));
+. unsigned int (*_bfd_canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **,
+. struct symbol_cache_entry **));
+. struct symbol_cache_entry *
+. (*_bfd_make_empty_symbol) PARAMS ((bfd *));
+. void (*_bfd_print_symbol) PARAMS ((bfd *, PTR,
+. struct symbol_cache_entry *,
+. bfd_print_symbol_type));
+.#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+. void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+. struct symbol_cache_entry *,
+. symbol_info *));
+.#define bfd_get_symbol_info(b,p,e) BFD_SEND(b, _bfd_get_symbol_info, (b,p,e))
+
+. alent * (*_get_lineno) PARAMS ((bfd *, struct symbol_cache_entry *));
+.
+. boolean (*_bfd_set_arch_mach) PARAMS ((bfd *, enum bfd_architecture,
+. unsigned long));
+.
+. bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
+.
+. boolean (*_bfd_find_nearest_line) PARAMS ((bfd *abfd,
+. struct sec *section, struct symbol_cache_entry **symbols,
+. bfd_vma offset, CONST char **file, CONST char **func,
+. unsigned int *line));
+.
+. int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+.
+. int (*_bfd_sizeof_headers) PARAMS ((bfd *, boolean));
+.
+. void (*_bfd_debug_info_start) PARAMS ((bfd *));
+. void (*_bfd_debug_info_end) PARAMS ((bfd *));
+. void (*_bfd_debug_info_accumulate) PARAMS ((bfd *, struct sec *));
+.
+. bfd_byte * (*_bfd_get_relocated_section_contents) PARAMS ((bfd *,
+. struct bfd_seclet *, bfd_byte *data,
+. boolean relocateable));
+.
+. boolean (*_bfd_relax_section) PARAMS ((bfd *, struct sec *,
+. struct symbol_cache_entry **));
+.
+. boolean (*_bfd_seclet_link) PARAMS ((bfd *, PTR data,
+. boolean relocateable));
+
+. {* See documentation on reloc types. *}
+. CONST struct reloc_howto_struct *
+. (*reloc_type_lookup) PARAMS ((bfd *abfd,
+. bfd_reloc_code_real_type code));
+.
+. {* Back-door to allow format-aware applications to create debug symbols
+. while using BFD for everything else. Currently used by the assembler
+. when creating COFF files. *}
+. asymbol * (*_bfd_make_debug_symbol) PARAMS ((
+. bfd *abfd,
+. void *ptr,
+. unsigned long size));
+
+Data for use by back-end routines, which isn't generic enough to belong
+in this structure.
+
+. PTR backend_data;
+.} bfd_target;
+
+*/
+
+/* All known xvecs (even those that don't compile on all systems).
+ Alphabetized for easy reference.
+ They are listed a second time below, since
+ we can't intermix extern's and initializers. */
+extern bfd_target a29kcoff_big_vec;
+extern bfd_target a_out_adobe_vec;
+extern bfd_target aout_mips_big_vec;
+extern bfd_target aout_mips_little_vec;
+extern bfd_target apollocoff_vec;
+extern bfd_target b_out_vec_big_host;
+extern bfd_target b_out_vec_little_host;
+extern bfd_target bfd_elf32_big_generic_vec;
+extern bfd_target bfd_elf32_bigmips_vec;
+extern bfd_target bfd_elf32_hppa_vec;
+extern bfd_target bfd_elf32_i386_vec;
+extern bfd_target bfd_elf32_i860_vec;
+extern bfd_target bfd_elf32_little_generic_vec;
+extern bfd_target bfd_elf32_littlemips_vec;
+extern bfd_target bfd_elf32_m68k_vec;
+extern bfd_target bfd_elf32_m88k_vec;
+extern bfd_target bfd_elf32_sparc_vec;
+extern bfd_target bfd_elf64_big_generic_vec;
+extern bfd_target bfd_elf64_little_generic_vec;
+extern bfd_target demo_64_vec;
+extern bfd_target ecoff_big_vec;
+extern bfd_target ecoff_little_vec;
+extern bfd_target ecoffalpha_little_vec;
+extern bfd_target h8300coff_vec;
+extern bfd_target h8500coff_vec;
+extern bfd_target host_aout_vec;
+extern bfd_target hp300bsd_vec;
+extern bfd_target hp300hpux_vec;
+extern bfd_target hppa_vec;
+extern bfd_target i386aout_vec;
+extern bfd_target i386bsd_vec;
+extern bfd_target netbsd386_vec;
+extern bfd_target freebsd386_vec;
+extern bfd_target i386coff_vec;
+extern bfd_target i386linux_vec;
+extern bfd_target i386lynx_aout_vec;
+extern bfd_target i386lynx_coff_vec;
+extern bfd_target icoff_big_vec;
+extern bfd_target icoff_little_vec;
+extern bfd_target ieee_vec;
+extern bfd_target m68kcoff_vec;
+extern bfd_target m68kcoffun_vec;
+extern bfd_target m68klynx_aout_vec;
+extern bfd_target m68klynx_coff_vec;
+extern bfd_target m88kbcs_vec;
+extern bfd_target newsos3_vec;
+extern bfd_target nlm32_big_generic_vec;
+extern bfd_target nlm32_i386_vec;
+extern bfd_target nlm32_little_generic_vec;
+extern bfd_target nlm64_big_generic_vec;
+extern bfd_target nlm64_little_generic_vec;
+extern bfd_target oasys_vec;
+extern bfd_target rs6000coff_vec;
+extern bfd_target shcoff_vec;
+extern bfd_target sunos_big_vec;
+extern bfd_target tekhex_vec;
+extern bfd_target we32kcoff_vec;
+extern bfd_target z8kcoff_vec;
+
+/* srec is always included. */
+extern bfd_target srec_vec;
+extern bfd_target symbolsrec_vec;
+
+/* All of the xvecs for core files. */
+extern bfd_target aix386_core_vec;
+extern bfd_target hpux_core_vec;
+extern bfd_target osf_core_vec;
+extern bfd_target sco_core_vec;
+extern bfd_target trad_core_vec;
+
+bfd_target *target_vector[] = {
+
+#ifdef SELECT_VECS
+
+ SELECT_VECS,
+
+#else /* not SELECT_VECS */
+
+#ifdef DEFAULT_VECTOR
+ &DEFAULT_VECTOR,
+#endif
+ /* This list is alphabetized to make it easy to compare
+ with other vector lists -- the decls above and
+ the case statement in configure.in.
+ Vectors that don't compile on all systems, or aren't finished,
+ should have an entry here with #if 0 around it, to show that
+ it wasn't omitted by mistake. */
+ &a29kcoff_big_vec,
+ &a_out_adobe_vec,
+#if 0 /* No one seems to use this. */
+ &aout_mips_big_vec,
+#endif
+ &aout_mips_little_vec,
+ &b_out_vec_big_host,
+ &b_out_vec_little_host,
+#if 0 /* No one seems to use this. */
+ &bfd_elf32_big_generic_vec,
+ &bfd_elf32_bigmips_vec,
+#endif
+#if 0
+ &bfd_elf32_hppa_vec,
+#endif
+ &bfd_elf32_i386_vec,
+ &bfd_elf32_i860_vec,
+#if 0 /* No one seems to use this. */
+ &bfd_elf32_little_generic_vec,
+ &bfd_elf32_littlemips_vec,
+#endif
+ &bfd_elf32_m68k_vec,
+ &bfd_elf32_m88k_vec,
+ &bfd_elf32_sparc_vec,
+#ifdef BFD64 /* No one seems to use this. */
+ &bfd_elf64_big_generic_vec,
+ &bfd_elf64_little_generic_vec,
+#endif
+#ifdef BFD64
+ &demo_64_vec, /* Only compiled if host has long-long support */
+#endif
+ &ecoff_big_vec,
+ &ecoff_little_vec,
+#if 0
+ &ecoffalpha_little_vec,
+#endif
+ &h8300coff_vec,
+ &h8500coff_vec,
+#if 0
+ &host_aout_vec,
+#endif
+#if 0 /* Clashes with sunos_big_vec magic no. */
+ &hp300bsd_vec,
+#endif
+ &hp300hpux_vec,
+#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD)
+ &hppa_vec,
+#endif
+ &i386aout_vec,
+ &i386bsd_vec,
+ &netbsd386_vec,
+ &freebsd386_vec,
+ &i386coff_vec,
+#if 0
+ &i386linux_vec,
+#endif
+ &i386lynx_aout_vec,
+ &i386lynx_coff_vec,
+ &icoff_big_vec,
+ &icoff_little_vec,
+ &ieee_vec,
+ &m68kcoff_vec,
+ &m68kcoffun_vec,
+ &m68klynx_aout_vec,
+ &m68klynx_coff_vec,
+ &m88kbcs_vec,
+ &newsos3_vec,
+#if 0 /* No one seems to use this. */
+ &nlm32_big_generic_vec,
+#endif
+ &nlm32_i386_vec,
+#if 0 /* No one seems to use this. */
+ &nlm32_little_generic_vec,
+#endif
+#ifdef BFD64
+ &nlm64_big_generic_vec,
+ &nlm64_little_generic_vec,
+#endif
+#if 0
+ /* We have no oasys tools anymore, so we can't test any of this
+ anymore. If you want to test the stuff yourself, go ahead...
+ steve@cygnus.com
+ Worse, since there is no magic number for archives, there
+ can be annoying target mis-matches. */
+ &oasys_vec,
+#endif
+ &rs6000coff_vec,
+ &shcoff_vec,
+ &sunos_big_vec,
+#if 0
+ &tekhex_vec,
+#endif
+ &we32kcoff_vec,
+ &z8kcoff_vec,
+
+#endif /* not SELECT_VECS */
+
+/* Always support S-records, for convenience. */
+ &srec_vec,
+ &symbolsrec_vec,
+
+/* Add any required traditional-core-file-handler. */
+
+#ifdef AIX386_CORE
+ &aix386_core_vec,
+#endif
+#ifdef HPUX_CORE
+ &hpux_core_vec,
+#endif
+#ifdef OSF_CORE
+ &osf_core_vec,
+#endif
+#ifdef SCO_CORE
+ &sco_core_vec,
+#endif
+#ifdef TRAD_CORE
+ &trad_core_vec,
+#endif
+
+ NULL /* end of list marker */
+};
+
+/* default_vector[0] contains either the address of the default vector,
+ if there is one, or zero if there isn't. */
+
+bfd_target *default_vector[] = {
+#ifdef DEFAULT_VECTOR
+ &DEFAULT_VECTOR,
+#endif
+ NULL
+};
+
+
+
+
+/*
+FUNCTION
+ bfd_find_target
+
+DESCRIPTION
+ 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 thenthe 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, and "target_defaulted" will be set in the
+ BFD. This causes <<bfd_check_format>> to loop over all the
+ targets to find the one that matches the file being read.
+
+SYNOPSIS
+ bfd_target *bfd_find_target(CONST char *, bfd *);
+*/
+
+bfd_target *
+DEFUN(bfd_find_target,(target_name, abfd),
+ CONST char *target_name AND
+ bfd *abfd)
+{
+ bfd_target **target;
+ extern char *getenv ();
+ CONST char *targname = (target_name ? target_name :
+ (CONST char *) getenv ("GNUTARGET"));
+
+ /* This is safe; the vector cannot be null */
+ if (targname == NULL || !strcmp (targname, "default")) {
+ abfd->target_defaulted = true;
+ return abfd->xvec = target_vector[0];
+ }
+
+ abfd->target_defaulted = false;
+
+ for (target = &target_vector[0]; *target != NULL; target++) {
+ if (!strcmp (targname, (*target)->name))
+ return abfd->xvec = *target;
+ }
+
+ bfd_error = invalid_target;
+ return NULL;
+}
+
+
+/*
+FUNCTION
+ bfd_target_list
+
+DESCRIPTION
+ This function returns a freshly malloced NULL-terminated
+ vector of the names of all the valid BFD targets. Do not
+ modify the names
+
+SYNOPSIS
+ CONST char **bfd_target_list(void);
+
+*/
+
+CONST char **
+DEFUN_VOID(bfd_target_list)
+{
+ int vec_length= 0;
+#ifdef NATIVE_HPPAHPUX_COMPILER
+ /* The native compiler on the HP9000/700 has a bug which causes it
+ to loop endlessly when compiling this file. This avoids it. */
+ volatile
+#endif
+ bfd_target **target;
+ CONST char **name_list, **name_ptr;
+
+ for (target = &target_vector[0]; *target != NULL; target++)
+ vec_length++;
+
+ name_ptr =
+ name_list = (CONST 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;
+}
diff --git a/gnu/usr.bin/gdb/bfd/trad-core.c b/gnu/usr.bin/gdb/bfd/trad-core.c
new file mode 100644
index 000000000000..203c80e6a832
--- /dev/null
+++ b/gnu/usr.bin/gdb/bfd/trad-core.c
@@ -0,0 +1,384 @@
+/* BFD back end for traditional Unix core files (U-area and raw sections)
+ Copyright 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by John Gilmore of Cygnus Support.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* To use this file on a particular host, configure the host with these
+ parameters in the config/h-HOST file:
+
+ HDEFINES=-DTRAD_CORE
+ HDEPFILES=trad-core.o
+
+ */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+
+#include <sys/user.h> /* After a.out.h */
+#if 0
+/* file.h is included by std-host.h. So we better not try to include it
+ twice; on some systems (dpx2) it is not protected against multiple
+ inclusion. I have checked that all the hosts which use this file
+ include sys/file.h in the hosts file. */
+#include <sys/file.h>
+#endif
+
+#include <errno.h>
+
+ struct trad_core_struct
+ {
+ asection *data_section;
+ asection *stack_section;
+ asection *reg_section;
+ struct user u;
+ } *rawptr;
+
+#define core_upage(bfd) (&((bfd)->tdata.trad_core_data->u))
+#define core_datasec(bfd) ((bfd)->tdata.trad_core_data->data_section)
+#define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section)
+#define core_regsec(bfd) ((bfd)->tdata.trad_core_data->reg_section)
+
+/* forward declarations */
+
+bfd_target * trad_unix_core_file_p PARAMS ((bfd *abfd));
+char * trad_unix_core_file_failing_command PARAMS ((bfd *abfd));
+int trad_unix_core_file_failing_signal PARAMS ((bfd *abfd));
+boolean trad_unix_core_file_matches_executable_p
+ PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+/* Handle 4.2-style (and perhaps also sysV-style) core dump file. */
+
+/* ARGSUSED */
+bfd_target *
+trad_unix_core_file_p (abfd)
+ bfd *abfd;
+
+{
+ int val;
+ struct user u;
+
+#ifdef TRAD_CORE_USER_OFFSET
+ /* If defined, this macro is the file position of the user struct. */
+ if (bfd_seek (abfd, TRAD_CORE_USER_OFFSET, SEEK_SET) == 0)
+ return 0;
+#endif
+
+ val = bfd_read ((void *)&u, 1, sizeof u, abfd);
+ if (val != sizeof u)
+ {
+ /* Too small to be a core file */
+ bfd_error = wrong_format;
+ return 0;
+ }
+
+ /* Sanity check perhaps??? */
+ if (u.u_dsize > 0x1000000) /* Remember, it's in pages... */
+ {
+ bfd_error = wrong_format;
+ return 0;
+ }
+ if (u.u_ssize > 0x1000000)
+ {
+ bfd_error = wrong_format;
+ return 0;
+ }
+
+ /* Check that the size claimed is no greater than the file size. */
+ {
+ FILE *stream = bfd_cache_lookup (abfd);
+ struct stat statbuf;
+ if (stream == NULL)
+ return 0;
+ if (fstat (fileno (stream), &statbuf) < 0)
+ {
+ bfd_error = system_call_error;
+ return 0;
+ }
+ if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) > statbuf.st_size)
+ {
+ bfd_error = file_truncated;
+ return 0;
+ }
+ if (NBPG * (UPAGES + u.u_dsize + u.u_ssize)
+#ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED
+ /* Some systems write the file too big. */
+ + TRAD_CORE_EXTRA_SIZE_ALLOWED
+#endif
+ < statbuf.st_size)
+ {
+ /* The file is too big. Maybe it's not a core file
+ or we otherwise have bad values for u_dsize and u_ssize). */
+ bfd_error = wrong_format;
+ return 0;
+ }
+ }
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+
+ /* Allocate both the upage and the struct core_data at once, so
+ a single free() will free them both. */
+ rawptr = (struct trad_core_struct *)
+ bfd_zalloc (abfd, sizeof (struct trad_core_struct));
+ if (rawptr == NULL) {
+ bfd_error = no_memory;
+ return 0;
+ }
+
+ abfd->tdata.trad_core_data = rawptr;
+
+ rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
+
+ /* Create the sections. This is raunchy, but bfd_close wants to free
+ them separately. */
+
+ 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) {
+ free ((void *)core_datasec (abfd));
+ goto loser1;
+ }
+
+ core_stacksec (abfd)->name = ".stack";
+ core_datasec (abfd)->name = ".data";
+ core_regsec (abfd)->name = ".reg";
+
+ core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
+ core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
+ core_regsec (abfd)->flags = SEC_ALLOC + SEC_HAS_CONTENTS;
+
+ core_datasec (abfd)->_raw_size = NBPG * u.u_dsize;
+ core_stacksec (abfd)->_raw_size = NBPG * u.u_ssize;
+ core_regsec (abfd)->_raw_size = NBPG * UPAGES; /* Larger than sizeof struct u */
+
+ /* What a hack... we'd like to steal it from the exec file,
+ since the upage does not seem to provide it. FIXME. */
+#ifdef HOST_DATA_START_ADDR
+ core_datasec (abfd)->vma = HOST_DATA_START_ADDR;
+#else
+ core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize);
+#endif
+/* a hack, but it works for FreeBSD !! */
+#include <vm/vm_param.h>
+/* this should really be in <vm/vm_param.h>, but somebody forgot it */
+#ifndef vm_page_size
+#define vm_page_size 4096
+#endif
+#define HOST_STACK_START_ADDR trunc_page(u.u_kproc.kp_eproc.e_vm.vm_maxsaddr \
++ MAXSSIZ - ctob(u.u_ssize))
+#ifdef HOST_STACK_START_ADDR
+ core_stacksec (abfd)->vma = HOST_STACK_START_ADDR;
+#else
+ core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize);
+#endif
+
+ /* This is tricky. As the "register section", we give them the entire
+ upage and stack. u.u_ar0 points to where "register 0" is stored.
+ There are two tricks with this, though. One is that the rest of the
+ registers might be at positive or negative (or both) displacements
+ from *u_ar0. The other is that u_ar0 is sometimes an absolute address
+ in kernel memory, and on other systems it is an offset from the beginning
+ of the `struct user'.
+
+ As a practical matter, we don't know where the registers actually are,
+ so we have to pass the whole area to GDB. We encode the value of u_ar0
+ by setting the .regs section up so that its virtual memory address
+ 0 is at the place pointed to by u_ar0 (by setting the vma of the start
+ of the section to -u_ar0). GDB uses this info to locate the regs,
+ using minor trickery to get around the offset-or-absolute-addr problem. */
+ core_regsec (abfd)->vma = 0 - (int) u.u_ar0;
+
+ core_datasec (abfd)->filepos = NBPG * UPAGES;
+#ifdef TRAD_CORE_STACK_FILEPOS
+ core_stacksec (abfd)->filepos = TRAD_CORE_STACK_FILEPOS;
+#else
+ core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize;
+#endif
+ core_regsec (abfd)->filepos = 0; /* Register segment is the upage */
+
+ /* Align to word at least */
+ core_stacksec (abfd)->alignment_power = 2;
+ core_datasec (abfd)->alignment_power = 2;
+ core_regsec (abfd)->alignment_power = 2;
+
+ abfd->sections = core_stacksec (abfd);
+ core_stacksec (abfd)->next = core_datasec (abfd);
+ core_datasec (abfd)->next = core_regsec (abfd);
+ abfd->section_count = 3;
+
+ return abfd->xvec;
+}
+
+char *
+trad_unix_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+#ifndef NO_CORE_COMMAND
+ char *com = abfd->tdata.trad_core_data->u.u_comm;
+ if (*com)
+ return com;
+ else
+#endif
+ return 0;
+}
+
+/* ARGSUSED */
+int
+trad_unix_core_file_failing_signal (ignore_abfd)
+ bfd *ignore_abfd;
+{
+#ifdef TRAD_UNIX_CORE_FILE_FAILING_SIGNAL
+ return TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(ignore_abfd);
+#else
+ return -1; /* FIXME, where is it? */
+#endif
+}
+
+/* ARGSUSED */
+boolean
+trad_unix_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ return true; /* FIXME, We have no way of telling at this point */
+}
+
+/* No archive file support via this BFD */
+#define trad_unix_openr_next_archived_file bfd_generic_openr_next_archived_file
+#define trad_unix_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define trad_unix_slurp_armap bfd_false
+#define trad_unix_slurp_extended_name_table bfd_true
+#define trad_unix_write_armap (boolean (*) PARAMS \
+ ((bfd *arch, unsigned int elength, struct orl *map, \
+ unsigned int orl_count, int stridx))) bfd_false
+#define trad_unix_truncate_arname bfd_dont_truncate_arname
+#define aout_32_openr_next_archived_file bfd_generic_openr_next_archived_file
+
+#define trad_unix_close_and_cleanup bfd_generic_close_and_cleanup
+#define trad_unix_set_section_contents (boolean (*) PARAMS \
+ ((bfd *abfd, asection *section, PTR data, file_ptr offset, \
+ bfd_size_type count))) bfd_false
+#define trad_unix_get_section_contents bfd_generic_get_section_contents
+#define trad_unix_new_section_hook (boolean (*) PARAMS \
+ ((bfd *, sec_ptr))) bfd_true
+#define trad_unix_get_symtab_upper_bound bfd_0u
+#define trad_unix_get_symtab (unsigned int (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry **))) bfd_0u
+#define trad_unix_get_reloc_upper_bound (unsigned int (*) PARAMS \
+ ((bfd *, sec_ptr))) bfd_0u
+#define trad_unix_canonicalize_reloc (unsigned int (*) PARAMS \
+ ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u
+#define trad_unix_make_empty_symbol (struct symbol_cache_entry * \
+ (*) PARAMS ((bfd *))) bfd_false
+#define trad_unix_print_symbol (void (*) PARAMS \
+ ((bfd *, PTR, struct symbol_cache_entry *, \
+ bfd_print_symbol_type))) bfd_false
+#define trad_unix_get_symbol_info (void (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry *, \
+ symbol_info *))) bfd_false
+#define trad_unix_get_lineno (alent * (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr
+#define trad_unix_set_arch_mach (boolean (*) PARAMS \
+ ((bfd *, enum bfd_architecture, unsigned long))) bfd_false
+#define trad_unix_find_nearest_line (boolean (*) PARAMS \
+ ((bfd *abfd, struct sec *section, \
+ struct symbol_cache_entry **symbols,bfd_vma offset, \
+ CONST char **file, CONST char **func, unsigned int *line))) bfd_false
+#define trad_unix_sizeof_headers (int (*) PARAMS \
+ ((bfd *, boolean))) bfd_0
+
+#define trad_unix_bfd_debug_info_start bfd_void
+#define trad_unix_bfd_debug_info_end bfd_void
+#define trad_unix_bfd_debug_info_accumulate (void (*) PARAMS \
+ ((bfd *, struct sec *))) bfd_void
+#define trad_unix_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
+#define trad_unix_bfd_relax_section bfd_generic_relax_section
+#define trad_unix_bfd_seclet_link \
+ ((boolean (*) PARAMS ((bfd *, PTR, boolean))) bfd_false)
+#define trad_unix_bfd_reloc_type_lookup \
+ ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
+#define trad_unix_bfd_make_debug_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+
+/* If somebody calls any byte-swapping routines, shoot them. */
+void
+swap_abort()
+{
+ abort(); /* This way doesn't require any declaration for ANSI to fuck up */
+}
+#define NO_GET ((bfd_vma (*) PARAMS (( bfd_byte *))) swap_abort )
+#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
+#define NO_SIGNED_GET ((bfd_signed_vma (*) PARAMS ((bfd_byte *))) swap_abort )
+
+bfd_target trad_core_vec =
+ {
+ "trad-core",
+ bfd_target_unknown_flavour,
+ 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, /* symbol prefix */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ 3, /* minimum alignment power */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ trad_unix_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ JUMP_TABLE(trad_unix),
+ (PTR) 0 /* backend_data */
+};
diff --git a/gnu/usr.bin/gdb/blockframe.c b/gnu/usr.bin/gdb/blockframe.c
deleted file mode 100644
index 236d1cdccfec..000000000000
--- a/gnu/usr.bin/gdb/blockframe.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)blockframe.c 6.4 (Berkeley) 5/11/91";
-#endif /* not lint */
-
-/* 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 <obstack.h>
-
-#if defined(NEWVM) && defined(KERNELDEBUG)
-#include <sys/param.h> /* XXX for FRAME_CHAIN_VALID */
-#endif
-
-/* 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? */
-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;
-
-struct block *block_for_pc ();
-CORE_ADDR get_pc_function_start ();
-
-/*
- * 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. */
-
-/* Many machines which allow frameless functions can detect them using
- this macro. Such machines should define FRAMELESS_FUNCTION_INVOCATION
- to just call this macro. */
-#define FRAMELESS_LOOK_FOR_PROLOGUE(FI, FRAMELESS) \
-{ \
- CORE_ADDR func_start, after_prologue; \
- func_start = (get_pc_function_start ((FI)->pc) + \
- FUNCTION_START_OFFSET); \
- if (func_start) \
- { \
- after_prologue = func_start; \
- SKIP_PROLOGUE (after_prologue); \
- (FRAMELESS) = (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. */ \
- (FRAMELESS) = 0; \
-}
-
-/* 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)
- {
- if (!have_inferior_p () && !have_core_file_p ())
- fatal ("get_prev_frame_info: Called before cache primed. \"Shouldn't happen.\"");
- else
- error ("No inferior or core file.");
- }
-
- 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 param.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;
- /* If this frame is a leaf, this will be superceeded by the
- code below. */
- address = FRAME_CHAIN_COMBINE (address, next_frame);
- }
- if (address == 0)
- return 0;
-
- 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. */
- prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (next_frame) :
- next_frame ? FRAME_SAVED_PC (next_frame) : read_pc ());
-
- return prev;
-}
-
-CORE_ADDR
-get_frame_pc (frame)
- FRAME frame;
-{
- struct frame_info *fi;
- fi = get_frame_info (frame);
- return fi->pc;
-}
-
-/* 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);
-}
-
-/* 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);
-}
-
-/* Return the innermost lexical block containing the specified pc value,
- or 0 if there is none. */
-
-extern struct symtab *psymtab_to_symtab ();
-
-struct block *
-block_for_pc (pc)
- register CORE_ADDR pc;
-{
- register struct block *b;
- register int bot, top, half;
- register struct symtab *s;
- register struct partial_symtab *ps;
- struct blockvector *bl;
-
- /* First search all symtabs for one whose file contains our pc */
-
- for (s = symtab_list; s; s = s->next)
- {
- bl = BLOCKVECTOR (s);
- b = BLOCKVECTOR_BLOCK (bl, 0);
- if (BLOCK_START (b) <= pc
- && BLOCK_END (b) > pc)
- break;
- }
-
- if (s == 0)
- for (ps = partial_symtab_list; ps; ps = ps->next)
- {
- if (ps->textlow <= pc
- && ps->texthigh > pc)
- {
- if (ps->readin)
- fatal ("Internal error: pc found in readin psymtab and not in any symtab.");
- s = psymtab_to_symtab (ps);
- bl = BLOCKVECTOR (s);
- b = BLOCKVECTOR_BLOCK (bl, 0);
- break;
- }
- }
-
- if (s == 0)
- return 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)
- return b;
- bot--;
- }
-
- 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);
-}
-
-/* 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 = find_pc_psymtab (pc);
- struct symbol *f;
- int miscfunc;
- struct partial_symbol *psb;
-
- 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 availible symbol. */
- if (name != 0)
- *name = 0;
- if (address != 0)
- *address = 0;
- return 0;
- }
-
- if (name)
- *name = SYMBOL_NAME (f);
- if (address)
- *address = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
- 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(psb)
- < misc_function_vector[miscfunc].address)))
- {
- if (address)
- *address = misc_function_vector[miscfunc].address;
- if (name)
- *name = misc_function_vector[miscfunc].name;
- return 1;
- }
- else
- {
- if (address)
- *address = SYMBOL_VALUE (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 (address)
- *address = misc_function_vector[miscfunc].address;
- if (name)
- *name = misc_function_vector[miscfunc].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;
- register int distance;
-
- /* 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;
- distance = misc_function_vector[new].address - pc;
- if (distance == 0)
- return new; /* an exact match */
- else if (distance > 0)
- 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/gnu/usr.bin/gdb/breakpoint.c b/gnu/usr.bin/gdb/breakpoint.c
deleted file mode 100644
index b515ed3f874f..000000000000
--- a/gnu/usr.bin/gdb/breakpoint.c
+++ /dev/null
@@ -1,1383 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)breakpoint.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* Everything about breakpoints, 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 "frame.h"
-
-/* This is the sequence of bytes we insert for a breakpoint. */
-
-static char break_insn[] = BREAKPOINT;
-
-/* 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 */
-
-struct breakpoint
-{
- struct breakpoint *next;
- /* Number assigned to distinguish breakpoints. */
- int number;
- /* Address to break at. */
- CORE_ADDR address;
- /* Line number of this address. Redundant. */
- int line_number;
- /* Symtab of file of this address. Redundant. */
- 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. */
- char shadow_contents[sizeof break_insn];
- /* Nonzero if this breakpoint is now inserted. */
- char inserted;
- /* Nonzero if this is not the first breakpoint in the list
- for the given address. */
- 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;
-};
-
-#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;
-
-/* 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;
-
-/* Remaining commands (not yet executed)
- of last breakpoint hit. */
-
-struct command_line *breakpoint_commands;
-
-static void delete_breakpoint ();
-void clear_momentary_breakpoints ();
-void breakpoint_auto_delete ();
-
-/* Flag indicating extra verbosity for xgdb. */
-extern int xgdb_verbose;
-
-/* 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;
- register char *p;
- register int bnum;
- register struct expression *expr;
-
- if (arg == 0)
- error_no_arg ("breakpoint number");
-
- p = arg;
- while (*p >= '0' && *p <= '9') p++;
- if (p == arg)
- /* There is no number here. (e.g. "cond a == b"). */
- error_no_arg ("breakpoint number");
- bnum = atoi (arg);
-
- ALL_BREAKPOINTS (b)
- if (b->number == bnum)
- {
- if (b->cond)
- {
- free (b->cond);
- b->cond = 0; /* parse_c_1 can leave this unchanged. */
- }
- if (*p == 0)
- {
- b->cond = 0;
- if (from_tty)
- printf ("Breakpoint %d now unconditional.\n", bnum);
- }
- else
- {
- if (*p != ' ' && *p != '\t')
- error ("Arguments must be an integer (breakpoint number) and an expression.");
-
- /* Find start of expression */
- while (*p == ' ' || *p == '\t') p++;
-
- arg = p;
- b->cond = (struct expression *) 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;
- register char *p, *p1;
- 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 (breakpoint_commands)
- error ("Can't use the \"commands\" command among a breakpoint's commands.");
-
- /* Allow commands by itself to refer to the last breakpoint. */
- if (arg == 0)
- bnum = breakpoint_count;
- else
- {
- p = arg;
- if (! (*p >= '0' && *p <= '9'))
- error ("Argument must be integer (a breakpoint number).");
-
- while (*p >= '0' && *p <= '9') p++;
- if (*p)
- error ("Unexpected extra arguments following breakpoint number.");
-
- bnum = atoi (arg);
- }
-
- ALL_BREAKPOINTS (b)
- if (b->number == bnum)
- {
- if (from_tty && 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 (from_tty);
- free_command_lines (b->commands);
- b->commands = l;
- return;
- }
- error ("No breakpoint number %d.", bnum);
-}
-
-/* Called from command loop to execute the commands
- associated with the breakpoint we just stopped at. */
-
-void
-do_breakpoint_commands ()
-{
- struct command_line *cmd;
-
- while (cmd = breakpoint_commands)
- {
- breakpoint_commands = 0;
- execute_command_lines(cmd);
- /* If command was "cont", breakpoint_commands is now 0,
- of if we stopped at yet another breakpoint which has commands,
- it is now the commands for the new breakpoint. */
- }
- clear_momentary_breakpoints ();
-}
-
-/* Used when the program is proceeded, to eliminate any remaining
- commands attached to the previous breakpoint we stopped at. */
-
-void
-clear_breakpoint_commands ()
-{
- breakpoint_commands = 0;
- breakpoint_auto_delete (0);
-}
-
-/* Functions to get and set the current list of pending
- breakpoint commands. These are used by run_stack_dummy
- to preserve the commands around a function call. */
-
-struct command_line *
-get_breakpoint_commands ()
-{
- return breakpoint_commands;
-}
-
-void
-set_breakpoint_commands (cmds)
- struct command_line *cmds;
-{
- breakpoint_commands = cmds;
-}
-
-/* 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;
-
-#ifdef BREAKPOINT_DEBUG
- printf ("Inserting breakpoints.\n");
-#endif /* BREAKPOINT_DEBUG */
-
- ALL_BREAKPOINTS (b)
- if (b->enable != disabled && ! b->inserted && ! b->duplicate)
- {
- read_memory (b->address, b->shadow_contents, sizeof break_insn);
- val = write_memory (b->address, break_insn, sizeof break_insn);
- if (val)
- return val;
-#ifdef BREAKPOINT_DEBUG
- printf ("Inserted breakpoint at 0x%x, shadow 0x%x, 0x%x.\n",
- b->address, b->shadow_contents[0], b->shadow_contents[1]);
-#endif /* BREAKPOINT_DEBUG */
- b->inserted = 1;
- }
- return 0;
-}
-
-int
-remove_breakpoints ()
-{
- register struct breakpoint *b;
- int val;
-
-#ifdef BREAKPOINT_DEBUG
- printf ("Removing breakpoints.\n");
-#endif /* BREAKPOINT_DEBUG */
-
- ALL_BREAKPOINTS (b)
- if (b->inserted)
- {
- val = write_memory (b->address, b->shadow_contents, sizeof break_insn);
- 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;
-}
-
-/* Evaluate the expression EXP and return 1 if value is zero.
- This is used inside a catch_errors to evaluate the breakpoint condition. */
-
-int
-breakpoint_cond_eval (exp)
- struct expression *exp;
-{
- return value_zerop (evaluate_expression (exp));
-}
-
-/* Return 0 if PC is not the address just after a breakpoint,
- or -1 if breakpoint says do not stop now,
- or -2 if breakpoint says it has deleted itself and don't stop,
- or -3 if hit a breakpoint number -3 (delete when program stops),
- or else the number of the breakpoint,
- with 0x1000000 added (or subtracted, for a negative return value) for
- a silent breakpoint. */
-
-int
-breakpoint_stop_status (pc, frame_address)
- CORE_ADDR pc;
- FRAME_ADDR frame_address;
-{
- register struct breakpoint *b;
- register int cont = 0;
-
- /* Get the address where the breakpoint would have been. */
- pc -= DECR_PC_AFTER_BREAK;
-
- ALL_BREAKPOINTS (b)
- if (b->enable != disabled && b->address == pc)
- {
- if (b->frame && b->frame != frame_address)
- cont = -1;
- 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, b->cond,
- "Error occurred in testing breakpoint condition.");
- free_all_values ();
- }
- if (b->cond && value_zero)
- {
- cont = -1;
- }
- else if (b->ignore_count > 0)
- {
- b->ignore_count--;
- cont = -1;
- }
- else
- {
- if (b->enable == temporary)
- b->enable = disabled;
- breakpoint_commands = b->commands;
- if (b->silent
- || (breakpoint_commands
- && !strcmp ("silent", breakpoint_commands->line)))
- {
- if (breakpoint_commands)
- breakpoint_commands = breakpoint_commands->next;
- return (b->number > 0 ?
- 0x1000000 + b->number :
- b->number - 0x1000000);
- }
- return b->number;
- }
- }
- }
-
- return cont;
-}
-
-static void
-breakpoint_1 (bnum)
- int bnum;
-{
- register struct breakpoint *b;
- register struct command_line *l;
- register struct symbol *sym;
- CORE_ADDR last_addr = (CORE_ADDR)-1;
-
- ALL_BREAKPOINTS (b)
- if (bnum == -1 || bnum == b->number)
- {
- printf_filtered ("#%-3d %c 0x%08x", b->number,
- "nyod"[(int) b->enable],
- 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 (" (", stdout);
- }
- fputs_filtered (b->symtab->filename, stdout);
- printf_filtered (" line %d", b->line_number);
- if (sym) fputs_filtered(")", stdout);
- }
- else
- print_address_symbolic (b->address, stdout);
-
- printf_filtered ("\n");
-
- if (b->ignore_count)
- printf_filtered ("\tignore next %d hits\n", b->ignore_count);
- if (b->frame)
- printf_filtered ("\tstop only in stack frame at 0x%x\n", b->frame);
- if (b->cond)
- {
- printf_filtered ("\tbreak only if ");
- print_expression (b->cond, stdout);
- printf_filtered ("\n");
- }
- if (l = b->commands)
- while (l)
- {
- printf_filtered ("\t%s\n", l->line);
- l = l->next;
- }
- }
-
- /* 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)
- char *bnum_exp;
-{
- int bnum = -1;
-
- if (bnum_exp)
- bnum = parse_and_eval_address (bnum_exp);
- else if (breakpoint_chain == 0)
- printf_filtered ("No breakpoints.\n");
- else
- printf_filtered ("Breakpoints:\n\
-Num Enb Address Where\n");
-
- breakpoint_1 (bnum);
-}
-
-/* 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);
- }
-}
-
-/* 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;
-
- /* 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;
- }
-}
-
-/* Set a breakpoint from a symtab and line.
- If TEMPFLAG is nonzero, it is a temporary breakpoint.
- Print the same confirmation messages that the breakpoint command prints. */
-
-void
-set_breakpoint (s, line, tempflag)
- struct symtab *s;
- int line;
- int tempflag;
-{
- 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);
- b->number = ++breakpoint_count;
- b->cond = 0;
- 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");
- }
-}
-
-/* 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;
- char *save_arg;
- 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 *)
- malloc (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
- /* 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, 0, 0);
-
- 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);
-}
-
-static 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);
-}
-
-/*
- * 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, 0, 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);
-}
-
-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 *) malloc (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
- && (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)
- error ("No breakpoint at %s.", arg);
-
- 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);
-}
-
-/* Delete breakpoint number BNUM if it is a `delete' breakpoint.
- This is called after breakpoint BNUM has been hit.
- Also delete any breakpoint numbered -3 unless there are breakpoint
- commands to be executed. */
-
-void
-breakpoint_auto_delete (bnum)
- int bnum;
-{
- register struct breakpoint *b;
- if (bnum != 0)
- ALL_BREAKPOINTS (b)
- if (b->number == bnum)
- {
- if (b->enable == delete)
- delete_breakpoint (b);
- break;
- }
- if (breakpoint_commands == 0)
- clear_momentary_breakpoints ();
-}
-
-static void
-delete_breakpoint (bpt)
- struct breakpoint *bpt;
-{
- register struct breakpoint *b;
-
- if (bpt->inserted)
- write_memory (bpt->address, bpt->shadow_contents, sizeof break_insn);
-
- 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 (xgdb_verbose && bpt->number >=0)
- printf ("breakpoint #%d deleted\n", bpt->number);
-
- free (bpt);
-}
-
-static void map_breakpoint_numbers ();
-
-static void
-delete_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- register struct breakpoint *b, *b1;
-
- if (arg == 0)
- {
- /* Ask user only if there are some breakpoints to delete. */
- if (!from_tty
- || breakpoint_chain && query ("Delete all breakpoints? "))
- {
- /* No arg; clear all breakpoints. */
- while (breakpoint_chain)
- delete_breakpoint (breakpoint_chain);
- }
- }
- else
- map_breakpoint_numbers (arg, delete_breakpoint);
-}
-
-/* Delete all breakpoints.
- Done when new symtabs are loaded, since the break condition expressions
- may become invalid, and the breakpoints are probably wrong anyway. */
-
-void
-clear_breakpoints ()
-{
- delete_command (0, 0);
-}
-
-/* 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;
-{
- register char *p = args;
- register int num;
-
- if (p == 0)
- error_no_arg ("a breakpoint number");
-
- while (*p >= '0' && *p <= '9') p++;
- if (*p && *p != ' ' && *p != '\t')
- error ("First argument must be a breakpoint number.");
-
- num = atoi (args);
-
- if (*p == 0)
- error ("Second argument (specified ignore-count) is missing.");
-
- set_ignore_count (num, parse_and_eval_address (p), from_tty);
- printf ("\n");
-}
-
-/* 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;
- register char *p1;
- register int num;
- register struct breakpoint *b;
-
- if (p == 0)
- error_no_arg ("one or more breakpoint numbers");
-
- while (*p)
- {
- p1 = p;
- while (*p1 >= '0' && *p1 <= '9') p1++;
- if (*p1 && *p1 != ' ' && *p1 != '\t')
- error ("Arguments must be breakpoint numbers.");
-
- num = atoi (p);
-
- ALL_BREAKPOINTS (b)
- if (b->number == num)
- {
- function (b);
- goto win;
- }
- printf ("No breakpoint number %d.\n", num);
- win:
- p = p1;
- while (*p == ' ' || *p == '\t') p++;
- }
-}
-
-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);
-}
-
-static void
-enable_command (args)
- char *args;
-{
- 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)
- char *args;
-{
- 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)
- char *args;
-{
- 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)
- char *args;
-{
- map_breakpoint_numbers (args, enable_delete_breakpoint);
-}
-
-/*
- * 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, 0, 0);
- if (*string)
- error ("Junk at end of line specification: %s", string);
- return sals;
-}
-
-
-/* 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;
- 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 or auto-display expressions.\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.\n\
-\n\
-The \"display\" subcommand applies to auto-displays instead of breakpoints.",
- &enablelist, "enable ", 1, &cmdlist);
-
- add_abbrev_prefix_cmd ("breakpoints", class_breakpoint, enable_command,
- "Enable some breakpoints or auto-display expressions.\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\
-May be abbreviates to simply \"enable\".\n\
-With a subcommand you can enable temporarily.",
- &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 or auto-display expressions.\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\
-\n\
-The \"display\" subcommand applies to auto-displays instead of breakpoints.",
- &disablelist, "disable ", 1, &cmdlist);
- add_com_alias ("dis", "disable", class_breakpoint, 1);
- add_com_alias ("disa", "disable", class_breakpoint, 1);
-
- add_abbrev_cmd ("breakpoints", class_breakpoint, disable_command,
- "Disable some breakpoints or auto-display expressions.\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.");
-}
-
diff --git a/gnu/usr.bin/gdb/command.h b/gnu/usr.bin/gdb/command.h
deleted file mode 100644
index fe28aef817ae..000000000000
--- a/gnu/usr.bin/gdb/command.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Header file for command-reading library command.c.
- 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. */
-
-/* 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. */
- int class;
-
- /* Function definition of this command.
- Zero for command class names and for help topics that
- are not really commands. */
- void (*function) ();
-
- /* 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;
- };
-
-/* 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 *lookup_cmd (), *lookup_cmd_1 ();
-extern char **complete_on_cmdlist ();
-extern void delete_cmd ();
-extern void help_cmd ();
diff --git a/gnu/usr.bin/gdb/config/Makefile.i386 b/gnu/usr.bin/gdb/config/Makefile.i386
deleted file mode 100644
index cc52aa3b13d4..000000000000
--- a/gnu/usr.bin/gdb/config/Makefile.i386
+++ /dev/null
@@ -1,6 +0,0 @@
-# @(#)Makefile.i386 6.2 (Berkeley) 3/21/91
-
-CONFIGSRCS= i386bsd-dep.c i386-pinsn.c
-
-param.h:
- ln -s $(.CURDIR)/config/m-i386bsd.h param.h
diff --git a/gnu/usr.bin/gdb/config/default-dep.c b/gnu/usr.bin/gdb/config/default-dep.c
deleted file mode 100644
index 13fe7b95a49e..000000000000
--- a/gnu/usr.bin/gdb/config/default-dep.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)default-dep.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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. */
-
-#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> Can we live without this? */
-
-#ifdef COFF_ENCAPSULATE
-#include "a.out.encap.h"
-#else
-#include <a.out.h>
-#endif
-#ifndef N_SET_MAGIC
-#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
-#endif
-
-#include <sys/user.h> /* After a.out.h */
-#include <sys/file.h>
-#include <sys/stat.h>
-
-extern int errno;
-
-/* 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, arg3, arg4)
- int request, pid, arg3, arg4;
-{
- return ptrace (request, pid, arg3, arg4);
-}
-
-kill_inferior ()
-{
- if (remote_debugging)
- return;
- if (inferior_pid == 0)
- return;
- ptrace (8, inferior_pid, 0, 0);
- wait (0);
- inferior_died ();
-}
-
-/* This is used when GDB is exiting. It gives less chance of error.*/
-
-kill_inferior_fast ()
-{
- if (remote_debugging)
- return;
- if (inferior_pid == 0)
- return;
- ptrace (8, inferior_pid, 0, 0);
- wait (0);
-}
-
-/* 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 (remote_debugging)
- remote_resume (step, signal);
- else
- {
- ptrace (step ? 9 : 7, inferior_pid, 1, signal);
- if (errno)
- perror_with_name ("ptrace");
- }
-}
-
-void
-fetch_inferior_registers ()
-{
- 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 (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
-
- for (regno = 0; regno < NUM_REGS; regno++)
- {
- regaddr = register_addr (regno, offset);
- 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];
-
- struct user u;
- unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
- offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
-
- if (regno >= 0)
- {
- regaddr = register_addr (regno, offset);
- 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);
- 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);
- }
- }
-}
-
-/* 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;
-{
- 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;
-
- /* Read all the longwords */
- for (i = 0; i < count; i++, addr += sizeof (int))
- {
- errno = 0;
-#if 0
- /* This is now done by read_memory, because when this function did it,
- reading a byte or short int hardware port read whole longs, causing
- serious side effects
- such as bus errors and unexpected hardware operation. This would
- also be a problem with ptrace if the inferior process could read
- or write hardware registers, but that's not usually the case. */
- if (remote_debugging)
- buffer[i] = remote_fetch_word (addr);
- else
-#endif
- buffer[i] = ptrace (1, inferior_pid, addr, 0);
- if (errno)
- return errno;
- }
-
- /* Copy appropriate bytes out of the buffer. */
- bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
- return 0;
-}
-
-/* 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. */
-
- if (remote_debugging)
- return (remote_write_inferior_memory(memaddr, myaddr, len));
-
- 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;
-}
-
-/* Work with core dump and executable files, for GDB.
- This code would be in core.c if it weren't machine-dependent. */
-
-#ifndef N_TXTADDR
-#define N_TXTADDR(hdr) 0
-#endif /* no N_TXTADDR */
-
-#ifndef N_DATADDR
-#define N_DATADDR(hdr) hdr.a_text
-#endif /* no N_DATADDR */
-
-/* Make COFF and non-COFF names for things a little more compatible
- to reduce conditionals later. */
-
-#ifdef COFF_FORMAT
-#define a_magic magic
-#endif
-
-#ifndef COFF_FORMAT
-#ifndef AOUTHDR
-#define AOUTHDR struct exec
-#endif
-#endif
-
-extern char *sys_siglist[];
-
-
-/* Hook for `exec_file_command' command to call. */
-
-extern void (*exec_file_display_hook) ();
-
-/* File names of core file and executable file. */
-
-extern char *corefile;
-extern char *execfile;
-
-/* Descriptors on which core file and executable file are open.
- Note that the execchan is closed when an inferior is created
- and reopened if the inferior dies or is killed. */
-
-extern int corechan;
-extern int execchan;
-
-/* Last modification time of executable file.
- Also used in source.c to compare against mtime of a source file. */
-
-extern int exec_mtime;
-
-/* Virtual addresses of bounds of the two areas of memory in the core file. */
-
-extern CORE_ADDR data_start;
-extern CORE_ADDR data_end;
-extern CORE_ADDR stack_start;
-extern CORE_ADDR stack_end;
-
-/* Virtual addresses of bounds of two areas of memory in the exec file.
- Note that the data area in the exec file is used only when there is no core file. */
-
-extern CORE_ADDR text_start;
-extern CORE_ADDR text_end;
-
-extern CORE_ADDR exec_data_start;
-extern CORE_ADDR exec_data_end;
-
-/* Address in executable file of start of text area data. */
-
-extern int text_offset;
-
-/* Address in executable file of start of data area data. */
-
-extern int exec_data_offset;
-
-/* Address in core file of start of data area data. */
-
-extern int data_offset;
-
-/* Address in core file of start of stack area data. */
-
-extern int stack_offset;
-
-#ifdef COFF_FORMAT
-/* various coff data structures */
-
-extern FILHDR file_hdr;
-extern SCNHDR text_hdr;
-extern SCNHDR data_hdr;
-
-#endif /* not COFF_FORMAT */
-
-/* a.out header saved in core file. */
-
-extern AOUTHDR core_aouthdr;
-
-/* a.out header of exec file. */
-
-extern AOUTHDR exec_aouthdr;
-
-extern void validate_files ();
-
-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);
-
- /* 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;
-
- /* 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");
-}
-
-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;
-
-#ifdef HEADER_SEEK_FD
- HEADER_SEEK_FD (execchan);
-#endif
-
- val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
-
- if (val < 0)
- perror_with_name (filename);
-
- text_start = N_TXTADDR (exec_aouthdr);
- exec_data_start = N_DATADDR (exec_aouthdr);
-
- text_offset = N_TXTOFF (exec_aouthdr);
- exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
-
- text_end = 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;
-
- if (fstat (execchan, &st_exec) < 0)
- perror_with_name (filename);
- 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);
-}
diff --git a/gnu/usr.bin/gdb/config/i386-dep.c b/gnu/usr.bin/gdb/config/i386-dep.c
deleted file mode 100644
index c4630d0c07ac..000000000000
--- a/gnu/usr.bin/gdb/config/i386-dep.c
+++ /dev/null
@@ -1,1275 +0,0 @@
-/* Low level interface to ptrace, for GDB when running on the Intel 386.
- 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"
-
-#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>
-
-#ifdef COFF_ENCAPSULATE
-#include "a.out.encap.h"
-#else
-#include <a.out.h>
-#endif
-
-#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>
-
-#include <sys/reg.h>
-
-extern int errno;
-
-/* 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, arg3, arg4)
- int request, pid, arg3, arg4;
-{
- return ptrace (request, pid, arg3, arg4);
-}
-
-kill_inferior ()
-{
- if (remote_debugging)
- return;
- if (inferior_pid == 0)
- return;
- ptrace (8, inferior_pid, 0, 0);
- wait (0);
- inferior_died ();
-}
-
-/* This is used when GDB is exiting. It gives less chance of error.*/
-
-kill_inferior_fast ()
-{
- if (remote_debugging)
- return;
- if (inferior_pid == 0)
- return;
- ptrace (8, inferior_pid, 0, 0);
- wait (0);
-}
-
-/* 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 (remote_debugging)
- remote_resume (step, signal);
- else
- {
- ptrace (step ? 9 : 7, inferior_pid, 1, signal);
- if (errno)
- perror_with_name ("ptrace");
- }
-}
-
-void
-fetch_inferior_registers ()
-{
- 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 (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
-
- for (regno = 0; regno < NUM_REGS; regno++)
- {
- regaddr = register_addr (regno, offset);
- 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];
-
- struct user u;
- unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
- offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
-
- if (regno >= 0)
- {
- regaddr = register_addr (regno, offset);
- 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);
- errno = 0;
- ptrace (6, inferior_pid, regaddr, read_register (regno));
- if (errno != 0)
- {
- sprintf (buf, "writing register number %d", regno);
- perror_with_name (buf);
- }
- }
-}
-
-/* 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;
-{
- 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;
-
- /* Read all the longwords */
- for (i = 0; i < count; i++, addr += sizeof (int))
- {
- errno = 0;
- if (remote_debugging)
- buffer[i] = remote_fetch_word (addr);
- else
- buffer[i] = ptrace (1, inferior_pid, addr, 0);
- if (errno)
- return errno;
- }
-
- /* Copy appropriate bytes out of the buffer. */
- bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
- return 0;
-}
-
-/* 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. */
-
- if (remote_debugging)
- buffer[0] = remote_fetch_word (addr);
- else
- buffer[0] = ptrace (1, inferior_pid, addr, 0);
-
- if (count > 1)
- {
- if (remote_debugging)
- buffer[count - 1]
- = remote_fetch_word (addr + (count - 1) * sizeof (int));
- else
- 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;
- if (remote_debugging)
- remote_store_word (addr, buffer[i]);
- else
- ptrace (4, inferior_pid, addr, buffer[i]);
- if (errno)
- return errno;
- }
-
- return 0;
-}
-
-/* Work with core dump and executable files, for GDB.
- This code would be in core.c if it weren't machine-dependent. */
-
-#ifndef N_TXTADDR
-#define N_TXTADDR(hdr) 0
-#endif /* no N_TXTADDR */
-
-#ifndef N_DATADDR
-#define N_DATADDR(hdr) hdr.a_text
-#endif /* no N_DATADDR */
-
-/* Make COFF and non-COFF names for things a little more compatible
- to reduce conditionals later. */
-
-#ifndef COFF_FORMAT
-#ifndef AOUTHDR
-#define AOUTHDR struct exec
-#endif
-#endif
-
-extern char *sys_siglist[];
-
-
-/* Hook for `exec_file_command' command to call. */
-
-extern void (*exec_file_display_hook) ();
-
-/* File names of core file and executable file. */
-
-extern char *corefile;
-extern char *execfile;
-
-/* Descriptors on which core file and executable file are open.
- Note that the execchan is closed when an inferior is created
- and reopened if the inferior dies or is killed. */
-
-extern int corechan;
-extern int execchan;
-
-/* Last modification time of executable file.
- Also used in source.c to compare against mtime of a source file. */
-
-extern int exec_mtime;
-
-/* Virtual addresses of bounds of the two areas of memory in the core file. */
-
-extern CORE_ADDR data_start;
-extern CORE_ADDR data_end;
-extern CORE_ADDR stack_start;
-extern CORE_ADDR stack_end;
-
-/* Virtual addresses of bounds of two areas of memory in the exec file.
- Note that the data area in the exec file is used only when there is no core file. */
-
-extern CORE_ADDR text_start;
-extern CORE_ADDR text_end;
-
-extern CORE_ADDR exec_data_start;
-extern CORE_ADDR exec_data_end;
-
-/* Address in executable file of start of text area data. */
-
-extern int text_offset;
-
-/* Address in executable file of start of data area data. */
-
-extern int exec_data_offset;
-
-/* Address in core file of start of data area data. */
-
-extern int data_offset;
-
-/* Address in core file of start of stack area data. */
-
-extern int stack_offset;
-
-#ifdef COFF_FORMAT
-/* various coff data structures */
-
-extern FILHDR file_hdr;
-extern SCNHDR text_hdr;
-extern SCNHDR data_hdr;
-
-#endif /* not COFF_FORMAT */
-
-/* a.out header saved in core file. */
-
-extern AOUTHDR core_aouthdr;
-
-/* a.out header of exec file. */
-
-extern AOUTHDR exec_aouthdr;
-
-extern void validate_files ();
-
-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. */
-/* N_SET_MAGIC (core_aouthdr, 0); */
- bzero ((char *) &core_aouthdr, sizeof core_aouthdr);
-
- /* 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");
-}
-
-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;
-
-#ifdef HEADER_SEEK_FD
- HEADER_SEEK_FD (execchan);
-#endif
-
- val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
-
- if (val < 0)
- perror_with_name (filename);
-
- text_start = N_TXTADDR (exec_aouthdr);
- exec_data_start = N_DATADDR (exec_aouthdr);
-
- text_offset = N_TXTOFF (exec_aouthdr);
- exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
-
- text_end = 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;
- }
-#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);
-}
-
-/* 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 %esp */
- {
- /* 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)
- 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;
- codestream_get();
- 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 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;
-
- 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;
-{
- 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[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;
-
- 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);
-}
-
-i386_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 ()));
-}
-
-/* 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]);
-
-}
-
-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/gnu/usr.bin/gdb/config/i386bsd-dep.c b/gnu/usr.bin/gdb/config/i386bsd-dep.c
deleted file mode 100644
index 80e11fa137c1..000000000000
--- a/gnu/usr.bin/gdb/config/i386bsd-dep.c
+++ /dev/null
@@ -1,1886 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)i386bsd-dep.c 6.10 (Berkeley) 6/26/91";
-#endif /* not lint */
-
-/* Low level interface to ptrace, for GDB when running on the Intel 386.
- 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 "value.h"
-
-#include <sys/param.h>
-#include <sys/dir.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-
-#include <a.out.h>
-
-#ifndef N_SET_MAGIC
-#define N_SET_MAGIC(exec, val) ((exec).a_magic = (val))
-#endif
-
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/uio.h>
-#define curpcb Xcurpcb /* XXX avoid leaking declaration from pcb.h */
-#include <sys/user.h>
-#undef curpcb
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/ptrace.h>
-
-#include <machine/reg.h>
-
-#ifdef KERNELDEBUG
-#ifndef NEWVM
-#include <sys/vmmac.h>
-#include <machine/pte.h>
-#else
-#include <sys/proc.h> /* for curproc */
-#endif
-#include <machine/vmparam.h>
-#include <machine/cpu.h>
-#include <ctype.h>
-#include "symtab.h" /* XXX */
-
-#undef vtophys /* XXX */
-
-extern int kernel_debugging;
-
-#define KERNOFF ((unsigned)KERNBASE)
-#ifndef NEWVM
-#define INKERNEL(x) ((x) >= KERNOFF && (x) < KERNOFF + ctob(slr))
-#define INUPAGE(x) \
- ((x) >= KERNEL_U_ADDR && (x) < KERNEL_U_ADDR + NBPG)
-#else
-#define INKERNEL(x) ((x) >= KERNOFF)
-#endif
-
-#define PT_ADDR_ANY ((caddr_t) 1)
-
-/*
- * Convert from sysmap pte index to system virtual address & vice-versa.
- * (why aren't these in one of the system vm macro files???)
- */
-#define smxtob(a) (sbr + (a) * sizeof(pte))
-#define btosmx(b) (((b) - sbr) / sizeof(pte))
-
-static int ok_to_cache();
-static int found_pcb;
-#ifdef NEWVM
-static CORE_ADDR curpcb;
-static CORE_ADDR kstack;
-#endif
-
-static void setregmap();
-
-extern int errno;
-
-/*
- * 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, arg3, arg4)
- int request;
- pid_t pid;
- caddr_t arg3;
- int arg4;
-{
- return(ptrace(request, pid, arg3, arg4));
-}
-
-kill_inferior()
-{
- if (remote_debugging) {
-#ifdef KERNELDEBUG
- if (kernel_debugging)
- /*
- * It's a very, very bad idea to go away leaving
- * breakpoints in a remote kernel or to leave it
- * stopped at a breakpoint.
- */
- clear_breakpoints();
-#endif
- remote_close(0);
- inferior_died();
- } else if (inferior_pid != 0) {
- ptrace(PT_KILL, inferior_pid, 0, 0);
- wait(0);
- inferior_died();
- }
-}
-
-/*
- * This is used when GDB is exiting. It gives less chance of error.
- */
-kill_inferior_fast()
-{
- if (remote_debugging) {
-#ifdef KERNELDEBUG
- if (kernel_debugging)
- clear_breakpoints();
-#endif
- remote_close(0);
- return;
- }
- if (inferior_pid == 0)
- return;
-
- ptrace(PT_KILL, inferior_pid, 0, 0);
- wait(0);
-}
-
-/*
- * 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 (remote_debugging)
- remote_resume(step, signal);
- else {
- ptrace(step ? PT_STEP : PT_CONTINUE, inferior_pid,
- PT_ADDR_ANY, signal);
- if (errno)
- perror_with_name("ptrace");
- }
-}
-
-#ifdef ATTACH_DETACH
-extern int attach_flag;
-
-/*
- * Start debugging the process whose number is PID.
- */
-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, PT_ADDR_ANY, signal);
- if (errno)
- perror_with_name("ptrace");
- attach_flag = 0;
-}
-#endif /* ATTACH_DETACH */
-
-static unsigned int
-get_register_offset()
-{
- unsigned int offset;
- struct user u; /* XXX */
- unsigned int flags = (char *) &u.u_pcb.pcb_flags - (char *) &u;
-
- setregmap(ptrace(PT_READ_U, inferior_pid, (caddr_t)flags, 0));
-
-#ifdef NEWVM
- offset = (char *) &u.u_kproc.kp_proc.p_regs - (char *) &u;
- offset = ptrace(PT_READ_U, inferior_pid, (caddr_t)offset, 0) -
- USRSTACK;
-#else
- offset = (char *) &u.u_ar0 - (char *) &u;
- offset = ptrace(PT_READ_U, inferior_pid, (caddr_t)offset, 0) -
- KERNEL_U_ADDR;
-#endif
-
- return offset;
-}
-
-void
-fetch_inferior_registers()
-{
- register int regno;
- register unsigned int regaddr;
- char buf[MAX_REGISTER_RAW_SIZE];
- register int i;
- unsigned int offset;
-
- if (remote_debugging) {
- extern char registers[];
-
- remote_fetch_registers(registers);
- return;
- }
-
- offset = get_register_offset();
-
- for (regno = 0; regno < NUM_REGS; regno++) {
- 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,
- (caddr_t)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];
- extern char registers[];
- register int i;
- unsigned int offset;
-
- if (remote_debugging) {
- extern char registers[];
-
- remote_store_registers(registers);
- return;
- }
-
- offset = get_register_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, (caddr_t)regaddr,
- *(int *) &registers[REGISTER_BYTE(regno) + i]);
- if (errno != 0) {
- sprintf(buf, "writing register number %d(%d)",
- regno, i);
- perror_with_name(buf);
- }
- regaddr += sizeof(int);
- }
- } else
- for (regno = 0; regno < NUM_REGS; regno++) {
- regaddr = register_addr(regno, offset);
- for (i = 0; i < REGISTER_RAW_SIZE(regno);
- i += sizeof(int)) {
- errno = 0;
- ptrace(PT_WRITE_U, inferior_pid,
- (caddr_t)regaddr,
- *(int *) &registers[REGISTER_BYTE(regno) + i]);
- if (errno != 0) {
- sprintf(buf,
- "writing register number %d(%d)",
- regno, i);
- perror_with_name(buf);
- }
- regaddr += sizeof(int);
- }
- }
-}
-
-/*
- * 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;
-{
- 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;
-
- if (remote_debugging)
- return (remote_read_inferior_memory(memaddr, myaddr, len));
-
- /* Read all the longwords */
- errno = 0;
- for (i = 0; i < count && errno == 0; i++, addr += sizeof(int))
- buffer[i] = ptrace(PT_READ_I, inferior_pid, (caddr_t)addr, 0);
-
- /* Copy appropriate bytes out of the buffer. */
- bcopy((char *) buffer + (memaddr & (sizeof(int) - 1)), myaddr, len);
- return(errno);
-}
-
-/*
- * 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.
- */
- if (remote_debugging)
- return (remote_write_inferior_memory(memaddr, myaddr, len));
-
- /*
- * Fill start and end extra bytes of buffer with existing memory
- * data.
- */
- buffer[0] = ptrace(PT_READ_I, inferior_pid, (caddr_t)addr, 0);
-
- if (count > 1)
- buffer[count - 1] = ptrace(PT_READ_I, inferior_pid,
- (caddr_t)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. */
-
- errno = 0;
- for (i = 0; i < count && errno == 0; i++, addr += sizeof(int))
- ptrace(PT_WRITE_I, inferior_pid, (caddr_t)addr, buffer[i]);
-
- return(errno);
-}
-
-
-/*
- * Work with core dump and executable files, for GDB.
- * This code would be in core.c if it weren't machine-dependent.
- */
-
-#ifndef N_TXTADDR
-#define N_TXTADDR(hdr) 0
-#endif /* no N_TXTADDR */
-
-#ifndef N_DATADDR
-#define N_DATADDR(hdr) hdr.a_text
-#endif /* no N_DATADDR */
-
-/*
- * Make COFF and non-COFF names for things a little more compatible to reduce
- * conditionals later.
- */
-
-#ifndef AOUTHDR
-#define AOUTHDR struct exec
-#endif
-
-extern char *sys_siglist[];
-
-
-/* Hook for `exec_file_command' command to call. */
-
-extern void (*exec_file_display_hook) ();
-
-/* File names of core file and executable file. */
-
-extern char *corefile;
-extern char *execfile;
-
-/* Descriptors on which core file and executable file are open.
- Note that the execchan is closed when an inferior is created
- and reopened if the inferior dies or is killed. */
-
-extern int corechan;
-extern int execchan;
-
-/* Last modification time of executable file.
- Also used in source.c to compare against mtime of a source file. */
-
-extern int exec_mtime;
-
-/* Virtual addresses of bounds of the two areas of memory in the core file. */
-
-extern CORE_ADDR data_start;
-extern CORE_ADDR data_end;
-extern CORE_ADDR stack_start;
-extern CORE_ADDR stack_end;
-
-/* Virtual addresses of bounds of two areas of memory in the exec file.
- Note that the data area in the exec file is used only when there is no core file. */
-
-extern CORE_ADDR text_start;
-extern CORE_ADDR text_end;
-
-extern CORE_ADDR exec_data_start;
-extern CORE_ADDR exec_data_end;
-
-/* Address in executable file of start of text area data. */
-
-extern int text_offset;
-
-/* Address in executable file of start of data area data. */
-
-extern int exec_data_offset;
-
-/* Address in core file of start of data area data. */
-
-extern int data_offset;
-
-/* Address in core file of start of stack area data. */
-
-extern int stack_offset;
-
-/* a.out header saved in core file. */
-
-extern AOUTHDR core_aouthdr;
-
-/* a.out header of exec file. */
-
-extern AOUTHDR exec_aouthdr;
-
-extern void validate_files ();
-
-extern int (*core_file_hook)();
-
-#ifdef KERNELDEBUG
-/*
- * Kernel debugging routines.
- */
-
-#define IOTOP 0x100000 /* XXX should get this from include file */
-#define IOBASE 0xa0000 /* XXX should get this from include file */
-
-static CORE_ADDR file_offset;
-static CORE_ADDR lowram;
-static CORE_ADDR sbr;
-static CORE_ADDR slr;
-static struct pcb pcb;
-
-static CORE_ADDR
-ksym_lookup(name)
- char *name;
-{
- struct symbol *sym;
- int i;
-
- if ((i = lookup_misc_func(name)) < 0)
- error("kernel symbol `%s' not found.", name);
-
- return (misc_function_vector[i].address);
-}
-
-/*
- * return true if 'len' bytes starting at 'addr' can be read out as
- * longwords and/or locally cached (this is mostly for memory mapped
- * i/o register access when debugging remote kernels).
- *
- * XXX the HP code does this differently with NEWVM
- */
-static int
-ok_to_cache(addr, len)
-{
- static CORE_ADDR atdevbase;
-
- if (! atdevbase)
- atdevbase = ksym_lookup("atdevbase");
-
- if (addr >= atdevbase && addr < atdevbase + (IOTOP - IOBASE))
- return (0);
-
- return (1);
-}
-
-static
-physrd(addr, dat, len)
- u_int addr;
- char *dat;
-{
- if (lseek(corechan, addr - file_offset, L_SET) == -1)
- return (-1);
- if (read(corechan, dat, len) != len)
- return (-1);
-
- return (0);
-}
-
-/*
- * When looking at kernel data space through /dev/mem or with a core file, do
- * virtual memory mapping.
- */
-#ifdef NEWVM
-static CORE_ADDR
-vtophys(addr)
- CORE_ADDR addr;
-{
- CORE_ADDR v;
- struct pte pte;
- static CORE_ADDR PTD = -1;
- CORE_ADDR current_ptd;
-
- /*
- * If we're looking at the kernel stack,
- * munge the address to refer to the user space mapping instead;
- * that way we get the requested process's kstack, not the running one.
- */
- if (addr >= kstack && addr < kstack + ctob(UPAGES))
- addr = (addr - kstack) + curpcb;
-
- /*
- * We may no longer have a linear system page table...
- *
- * Here's the scoop. IdlePTD contains the physical address
- * of a page table directory that always maps the kernel.
- * IdlePTD is in memory that is mapped 1-to-1, so we can
- * find it easily given its 'virtual' address from ksym_lookup().
- * For hysterical reasons, the value of IdlePTD is stored in sbr.
- *
- * To look up a kernel address, we first convert it to a 1st-level
- * address and look it up in IdlePTD. This gives us the physical
- * address of a page table page; we extract the 2nd-level part of
- * VA and read the 2nd-level pte. Finally, we add the offset part
- * of the VA into the physical address from the pte and return it.
- *
- * User addresses are a little more complicated. If we don't have
- * a current PCB from read_pcb(), we use PTD, which is the (fixed)
- * virtual address of the current ptd. Since it's NOT in 1-to-1
- * kernel space, we must look it up using IdlePTD. If we do have
- * a pcb, we get the ptd from pcb_ptd.
- */
-
- if (INKERNEL(addr))
- current_ptd = sbr;
- else if (found_pcb == 0) {
- if (PTD == -1)
- PTD = vtophys(ksym_lookup("PTD"));
- current_ptd = PTD;
- } else
- current_ptd = pcb.pcb_ptd;
-
- /*
- * Read the first-level page table (ptd).
- */
- v = current_ptd + ((unsigned)addr >> PD_SHIFT) * sizeof pte;
- if (physrd(v, (char *)&pte, sizeof pte) || pte.pg_v == 0)
- return (~0);
-
- /*
- * Read the second-level page table.
- */
- v = i386_ptob(pte.pg_pfnum) + ((addr&PT_MASK) >> PG_SHIFT) * sizeof pte;
- if (physrd(v, (char *) &pte, sizeof(pte)) || pte.pg_v == 0)
- return (~0);
-
- addr = i386_ptob(pte.pg_pfnum) + (addr & PGOFSET);
-#if 0
- printf("vtophys(%x) -> %x\n", oldaddr, addr);
-#endif
- return (addr);
-}
-#else
-static CORE_ADDR
-vtophys(addr)
- CORE_ADDR addr;
-{
- CORE_ADDR v;
- struct pte pte;
- CORE_ADDR oldaddr = addr;
-
- if (found_pcb == 0 && INUPAGE(addr)) {
- static CORE_ADDR pSwtchmap;
-
- if (pSwtchmap == 0)
- pSwtchmap = vtophys(ksym_lookup("Swtchmap"));
- addr = pSwtchmap;
- } else if (INKERNEL(addr)) {
- /*
- * In system space get system pte. If valid or reclaimable
- * then physical address is combination of its page number
- * and the page offset of the original address.
- */
- addr = smxtob(btop(addr - KERNOFF)) - KERNOFF;
- } else {
- v = btop(addr);
- if (v < pcb.pcb_p0lr)
- addr = (CORE_ADDR) pcb.pcb_p0br +
- v * sizeof (struct pte);
- else if (v >= pcb.pcb_p1lr && v < P1PAGES)
- addr = (CORE_ADDR) pcb.pcb_p0br +
- ((pcb.pcb_szpt * NPTEPG - HIGHPAGES) -
- (BTOPUSRSTACK - v)) * sizeof (struct pte);
- else
- return (~0);
-
- /*
- * For p0/p1 address, user-level page table should be in
- * kernel vm. Do second-level indirect by recursing.
- */
- if (!INKERNEL(addr))
- return (~0);
-
- addr = vtophys(addr);
- }
- /*
- * Addr is now address of the pte of the page we are interested in;
- * get the pte and paste up the physical address.
- */
- if (physrd(addr, (char *) &pte, sizeof(pte)))
- return (~0);
-
- if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0))
- return (~0);
-
- addr = (CORE_ADDR)ptob(pte.pg_pfnum) + (oldaddr & PGOFSET);
-#if 0
- printf("vtophys(%x) -> %x\n", oldaddr, addr);
-#endif
- return (addr);
-}
-
-#endif
-
-static
-kvread(addr)
- CORE_ADDR addr;
-{
- CORE_ADDR paddr = vtophys(addr);
-
- if (paddr != ~0)
- if (physrd(paddr, (char *)&addr, sizeof(addr)) == 0);
- return (addr);
-
- return (~0);
-}
-
-static void
-read_pcb(uaddr)
- u_int uaddr;
-{
- int i;
- int *pcb_regs = (int *)&pcb;
-
-#ifdef NEWVM
- if (physrd(uaddr, (char *)&pcb, sizeof pcb))
- error("cannot read pcb at %x\n", uaddr);
- printf("current pcb at %x\n", uaddr);
-#else
- if (physrd(uaddr, (char *)&pcb, sizeof pcb))
- error("cannot read pcb at %x\n", uaddr);
- printf("p0br %x p0lr %x p1br %x p1lr %x\n",
- pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
-#endif
-
- /*
- * get the register values out of the sys pcb and
- * store them where `read_register' will find them.
- */
- for (i = 0; i < 8; ++i)
- supply_register(i, &pcb_regs[i+10]);
- supply_register(8, &pcb_regs[8]); /* eip */
- supply_register(9, &pcb_regs[9]); /* eflags */
- for (i = 10; i < 13; ++i) /* cs, ss, ds */
- supply_register(i, &pcb_regs[i+9]);
- supply_register(13, &pcb_regs[18]); /* es */
- for (i = 14; i < 16; ++i) /* fs, gs */
- supply_register(i, &pcb_regs[i+8]);
-
- /* XXX 80387 registers? */
-}
-
-static void
-setup_kernel_debugging()
-{
- struct stat stb;
- int devmem = 0;
- CORE_ADDR addr;
-
- fstat(corechan, &stb);
- if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0))
- devmem = 1;
-
-#ifdef NEWVM
- physrd(ksym_lookup("IdlePTD") - KERNOFF, &sbr, sizeof sbr);
- slr = 2 * NPTEPG; /* XXX temporary */
- printf("IdlePTD %x\n", sbr);
- curpcb = ksym_lookup("curpcb") - KERNOFF;
- physrd(curpcb, &curpcb, sizeof curpcb);
- kstack = ksym_lookup("kstack");
-#else
- sbr = ksym_lookup("Sysmap");
- slr = ksym_lookup("Syssize");
- printf("sbr %x slr %x\n", sbr, slr);
-#endif
-
- /*
- * pcb where "panic" saved registers in first thing in current
- * u area.
- */
-#ifndef NEWVM
- read_pcb(vtophys(ksym_lookup("u")));
-#endif
- found_pcb = 1;
- if (!devmem) {
- /* find stack frame */
- CORE_ADDR panicstr;
- char buf[256];
- register char *cp;
-
- panicstr = kvread(ksym_lookup("panicstr"));
- if (panicstr == ~0)
- return;
- (void) kernel_core_file_hook(panicstr, buf, sizeof(buf));
- for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
- if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
- *cp = '?';
- if (*cp)
- *cp = '\0';
- printf("panic: %s\n", buf);
- read_pcb(ksym_lookup("dumppcb") - KERNOFF);
- }
-#ifdef NEWVM
- else
- read_pcb(vtophys(kstack));
-#endif
-
- stack_start = USRSTACK;
- stack_end = USRSTACK + ctob(UPAGES);
-}
-
-set_paddr_command(arg)
- char *arg;
-{
- u_int uaddr;
-
- if (!arg)
- error_no_arg("ps-style address for new current process");
- if (!kernel_debugging)
- error("not debugging kernel");
- uaddr = (u_int) parse_and_eval_address(arg);
-#ifndef NEWVM
- read_pcb(ctob(uaddr));
-#else
- /* p_addr is now a pcb virtual address */
- read_pcb(vtophys(uaddr));
- curpcb = uaddr;
-#endif
-
- flush_cached_frames();
- set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc()));
- select_frame(get_current_frame(), 0);
-}
-
-/*
- * read len bytes from kernel virtual address 'addr' into local
- * buffer 'buf'. Return 0 if read ok, 1 otherwise. On read
- * errors, portion of buffer not read is zeroed.
- */
-kernel_core_file_hook(addr, buf, len)
- CORE_ADDR addr;
- char *buf;
- int len;
-{
- int i;
- CORE_ADDR paddr;
-
- while (len > 0) {
- paddr = vtophys(addr);
- if (paddr == ~0) {
- bzero(buf, len);
- return (1);
- }
- /* we can't read across a page boundary */
- i = min(len, NBPG - (addr & PGOFSET));
- if (physrd(paddr, buf, i)) {
- bzero(buf, len);
- return (1);
- }
- buf += i;
- addr += i;
- len -= i;
- }
- return (0);
-}
-#endif
-
-core_file_command(filename, from_tty)
- char *filename;
- int from_tty;
-{
- int val;
- extern char registers[];
-#ifdef KERNELDEBUG
- struct stat stb;
-#endif
-
- /*
- * Discard all vestiges of any previous core file and mark data and
- * stack spaces as empty.
- */
- if (corefile)
- free(corefile);
- corefile = 0;
- core_file_hook = 0;
-
- if (corechan >= 0)
- close(corechan);
- corechan = -1;
-
- /* Now, if a new core file was specified, open it and digest it. */
-
- if (filename == 0) {
- if (from_tty)
- printf("No core file now.\n");
- return;
- }
- 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);
-
-#ifdef KERNELDEBUG
- fstat(corechan, &stb);
-
- if (kernel_debugging) {
- setup_kernel_debugging();
- core_file_hook = kernel_core_file_hook;
- } else if ((stb.st_mode & S_IFMT) == S_IFCHR &&
- stb.st_rdev == makedev(2, 1)) {
- /* looking at /dev/kmem */
- data_offset = data_start = KERNOFF;
- data_end = ~0; /* XXX */
- stack_end = stack_start = data_end;
- } else
-#endif
- {
- /*
- * 4.2-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);
-
- /*
- * 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;
-
-#ifndef NEWVM
- 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 - KERNEL_U_ADDR;
-#else
- data_end = data_start +
- NBPG * u.u_kproc.kp_eproc.e_vm.vm_dsize;
- stack_start = stack_end -
- NBPG * u.u_kproc.kp_eproc.e_vm.vm_ssize;
- data_offset = NBPG * UPAGES;
- stack_offset = NBPG *
- (UPAGES + u.u_kproc.kp_eproc.e_vm.vm_dsize);
-
- reg_offset = (int) u.u_kproc.kp_proc.p_regs - USRSTACK;
-#endif
-
- setregmap(u.u_pcb.pcb_flags);
-
- /*
- * I don't know where to find this info. So, for now,
- * mark it as not available.
- */
- /* N_SET_MAGIC (core_aouthdr, 0); */
- bzero ((char *) &core_aouthdr, sizeof core_aouthdr);
-
- /*
- * 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);
- }
- }
- }
-#endif
- 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();
-}
-
-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 = 0;
- stack_start = 0;
- stack_end = 0;
- 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);
-
- {
- struct stat st_exec;
-
-#ifdef HEADER_SEEK_FD
- HEADER_SEEK_FD(execchan);
-#endif
-
- val = myread(execchan, &exec_aouthdr, sizeof(AOUTHDR));
-
- if (val < 0)
- perror_with_name(filename);
-
-#ifdef KERNELDEBUG
- if (kernel_debugging) {
- /* Gross and disgusting XXX */
- text_start = KERNTEXT_BASE;
- exec_data_start = KERNTEXT_BASE +
- (exec_aouthdr.a_text + 4095) & ~ 4095;
- } else {
-#endif
- text_start = N_TXTADDR(exec_aouthdr);
- exec_data_start = N_DATADDR(exec_aouthdr);
-#ifdef KERNELDEBUG
- }
-#endif
-
- text_offset = N_TXTOFF(exec_aouthdr);
- exec_data_offset = N_TXTOFF(exec_aouthdr) + exec_aouthdr.a_text;
-
- text_end = text_start + exec_aouthdr.a_text;
- exec_data_end = exec_data_start + exec_aouthdr.a_data;
-
- 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);
-}
-
-int dummy_code[] = {
- 0xb8909090, /* nop; nop; nop; movl $0x32323232,%eax */
- 0x32323232,
-#define DUMMY_CALL_INDEX 1
- 0x90ccd0ff, /* call %eax; int3; nop */
-};
-
-/*
- * Build `dummy' call instructions on inferior's stack to cause
- * it to call a subroutine.
- *
- * N.B. - code in wait_for_inferior requires that sp < pc < fp when
- * we take the trap 2 above so it will recognize that we stopped
- * at a `dummy' call. So, after the call sp is *not* decremented
- * to clean the arguments, code & other stuff we lay on the stack.
- * Since the regs are restored to saved values at the breakpoint,
- * sp will get reset correctly. Also, this restore means we don't
- * have to construct frame linkage info to save pc & fp. The lack
- * of frame linkage means we can't do a backtrace, etc., if the
- * called function gets a fault or hits a breakpoint but code in
- * run_stack_dummy makes this impossible anyway.
- */
-CORE_ADDR
-setup_dummy(sp, funaddr, nargs, args, struct_return_bytes, pushfn)
- CORE_ADDR sp;
- CORE_ADDR funaddr;
- int nargs;
- value *args;
- int struct_return_bytes;
- CORE_ADDR (*pushfn)();
-{
- int padding, i;
- CORE_ADDR top = sp, struct_addr, pc;
-
- i = arg_stacklen(nargs, args) + struct_return_bytes
- + sizeof(dummy_code);
- if (i & 3)
- padding = 4 - (i & 3);
- else
- padding = 0;
- pc = sp - sizeof(dummy_code);
- sp = pc - padding - struct_return_bytes;
- struct_addr = sp;
- while (--nargs >= 0)
- sp = (*pushfn)(sp, *args++);
- if (struct_return_bytes)
- STORE_STRUCT_RETURN(struct_addr, sp);
- write_register(SP_REGNUM, sp);
-
- dummy_code[DUMMY_CALL_INDEX] = (int)funaddr;
- write_memory(pc, (char *)dummy_code, sizeof(dummy_code));
-
- return pc;
-}
-
-/* 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 %esp */
- {
- /* 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)
- 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;
- codestream_get();
- 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 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;
-
- 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;
-{
- unsigned long locals;
- unsigned char *p;
- unsigned char op;
- CORE_ADDR dummy_bottom;
- CORE_ADDR adr;
- int i;
-
- bzero (fsrp, sizeof *fsrp);
-
-#if 0
- /* 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;
- }
-#endif
-
- 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_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 ()));
-}
-
-/* this table must line up with REGISTER_NAMES in m-i386.h */
-/* symbols like 'EAX' come from <sys/reg.h> */
-static int trapmap[] =
-{
- tEAX, tECX, tEDX, tEBX,
- tESP, tEBP, tESI, tEDI,
- tEIP, tEFLAGS, tCS, tSS,
- tDS, tES, tES, tES /* lies: no fs or gs */
-};
-#if defined(FM_TRAP) || defined(EX_TRAPSTK)
-static int syscallmap[] =
-{
- sEAX, sECX, sEDX, sEBX,
- sESP, sEBP, sESI, sEDI,
- sEIP, sEFLAGS, sCS, sSS,
- sCS, sCS, sCS, sCS /* lies: no ds, es, fs or gs */
-};
-#endif
-static int *regmap;
-
-static void
-setregmap(flags)
- int flags;
-{
-#ifdef FM_TRAP
- regmap = flags & FM_TRAP ? trapmap: syscallmap;
-#elif EX_TRAPSTK
- regmap = flags & EX_TRAPSTK ? trapmap : syscallmap;
-#else
- regmap = trapmap; /* the lesser evil */
-#endif
-}
-
-/* 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]);
-}
-
-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--)
- {
- int st_regno;
- double val;
-
- /* The physical regno `fpreg' is only relevant as an index into the
- * tag word. Logical `%st' numbers are required for indexing `p->regs.
- */
- st_regno = (fpreg + 8 - top) & 0x7;
-
- printf ("%%st(%d) %s ", st_regno, fpreg == top ? "=>" : " ");
-
- 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[st_regno][i]);
-
- i387_to_double (ep->regs[st_regno], (char *)&val);
- printf (" %g\n", val);
- }
-#if 0 /* reserved fields are always 0xffff on 486's */
- 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);
-#endif
-}
-
-#ifdef __386BSD__
-#define fpstate save87
-#define U_FPSTATE(u) u.u_pcb.pcb_savefpu
-#endif
-
-#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;
-
-#ifndef __386BSD__ /* XXX - look at pcb flags */
- uaddr = (char *)&u.u_fpvalid - (char *)&u;
- if (have_inferior_p())
- {
- unsigned int data;
- unsigned int mask;
-
- rounded_addr = uaddr & -sizeof (int);
- data = ptrace (PT_READ_U, inferior_pid, (caddr_t)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;
- }
-#endif /* not __386BSD__ */
-
- 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 (PT_READ_U, inferior_pid, (caddr_t)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;
- }
-
-#ifdef __386BSD__
- print_387_status (0, (struct env387 *)buf);
-#else
- fpstatep = (struct fpstate *)(buf + skip);
- print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
-#endif
-}
-
-void
-_initialize_i386bsd_dep()
-{
-#ifdef KERNELDEBUG
- add_com ("process-address", class_obscure, set_paddr_command,
- "The process identified by (ps-style) ADDR becomes the\n\
-\"current\" process context for kernel debugging.");
- add_com_alias ("paddr", "process-address", class_obscure, 0);
-#endif
-}
diff --git a/gnu/usr.bin/gdb/config/m-i386-sv32.h b/gnu/usr.bin/gdb/config/m-i386-sv32.h
deleted file mode 100644
index 38fb4eb6d5b6..000000000000
--- a/gnu/usr.bin/gdb/config/m-i386-sv32.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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 "m-i386.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/gnu/usr.bin/gdb/config/m-i386bsd.h b/gnu/usr.bin/gdb/config/m-i386bsd.h
deleted file mode 100644
index 15d97b23d339..000000000000
--- a/gnu/usr.bin/gdb/config/m-i386bsd.h
+++ /dev/null
@@ -1,375 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1991 by William Jolitz at UUNET Technologies, Inc.
- *
- * @(#)m-i386bsd.h 6.7 (Berkeley) 5/8/91
- */
-
-/* Macro definitions 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. */
-
-/* Define the bit, byte, and word ordering of the machine. */
-/* #define BITS_BIG_ENDIAN */
-/* #define BYTES_BIG_ENDIAN */
-/* #define WORDS_BIG_ENDIAN */
-
-/*
- * Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
- * July 1988
- * [ MODIFIED FOR 386BSD W. Jolitz ]
- */
-
-#ifndef i386
-#define i386 1
-#define i386b 1
-#endif
-
-#define IEEE_FLOAT
-#define LONG_LONG
-
-/* Library stuff: POSIX tty (not supported yet), V7 tty (sigh), vprintf. */
-
-#define HAVE_TERMIOS 1
-#define USE_OLD_TTY 1
-#define HAVE_VPRINTF 1
-
-/* We support local and remote kernel debugging. */
-
-#define KERNELDEBUG 1
-
-/* Get rid of any system-imposed stack limit if possible. */
-
-#define SET_STACK_LIMIT_HUGE
-
-/* 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
-
-/* 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
-
-/* 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 the amount to subtract from u.u_ar0
- to get the offset in the core file of the register values. */
-
-#ifdef NEWVM
-#include <machine/vmparam.h>
-#define KERNEL_U_ADDR USRSTACK
-#else
-#define KERNEL_U_ADDR 0xfdffd000
-#endif
-
-/* Address of end of stack space. */
-
-#define STACK_END_ADDR KERNEL_U_ADDR
-
-/* 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) \
- strchr("\302\303\312\313\317", read_memory_integer(pc, 1))
-
-/* 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 (); }
-
-
-/* Largest integer type */
-#define LONGEST long long
-
-/* Name of the builtin type for the LONGEST type above. */
-#define BUILTIN_TYPE_LONGEST builtin_type_long_long
-
-/* 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))
-
-
-/* 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)
-
-#ifdef KERNELDEBUG
-#define KERNTEXT_BASE 0xfe000000
-#ifdef NEWVM
-#define KERNSTACK_TOP (read_register(SP_REGNUM) + 0x2000) /* approximate */
-#else
-/* #define KERNSTACK_TOP (P1PAGES << PGSHIFT) */
-#define KERNSTACK_TOP 0xfe000000
-#endif
-extern int kernel_debugging;
-#define FRAME_CHAIN_VALID(chain, thisframe) \
- (chain != 0 && \
- !kernel_debugging ? outside_startup_file(FRAME_SAVED_PC(thisframe)) :\
- (chain >= read_register(SP_REGNUM) && chain < KERNSTACK_TOP))
-#else
-#define FRAME_CHAIN_VALID(chain, thisframe) \
- (chain != 0 && (outside_startup_file (FRAME_SAVED_PC (thisframe))))
-#endif
-
-#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_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
-
-#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)); }
-
-
-/* Discard from the stack the innermost frame, restoring all registers. */
-
-#define POP_FRAME { i386_pop_frame (); }
-
-#define NEW_CALL_FUNCTION
-
-#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
diff --git a/gnu/usr.bin/gdb/config/m-i386g-sv32.h b/gnu/usr.bin/gdb/config/m-i386g-sv32.h
deleted file mode 100644
index 3d69eea184e0..000000000000
--- a/gnu/usr.bin/gdb/config/m-i386g-sv32.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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 "m-i386gas.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/gnu/usr.bin/gdb/config/m-i386gas.h b/gnu/usr.bin/gdb/config/m-i386gas.h
deleted file mode 100644
index fbd21385cc77..000000000000
--- a/gnu/usr.bin/gdb/config/m-i386gas.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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 "m-i386.h"
-
-
-#define NAMES_HAVE_UNDERSCORE
-
-#undef COFF_FORMAT
-#define READ_DBX_FORMAT
-
diff --git a/gnu/usr.bin/gdb/copying.c b/gnu/usr.bin/gdb/copying.c
deleted file mode 100644
index b3d75198078e..000000000000
--- a/gnu/usr.bin/gdb/copying.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* Do not modify this file; it is created automatically
- by copying.awk. */
-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 (" \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 (" \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 (" \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/gnu/usr.bin/gdb/core.c b/gnu/usr.bin/gdb/core.c
deleted file mode 100644
index 307addb54ae1..000000000000
--- a/gnu/usr.bin/gdb/core.c
+++ /dev/null
@@ -1,581 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)core.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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 "defs.h"
-#include "param.h"
-#include "frame.h" /* required by inferior.h */
-#include "inferior.h"
-
-#ifdef USG
-#include <sys/types.h>
-#include <fcntl.h>
-#endif
-
-#ifdef COFF_ENCAPSULATE
-#include "a.out.encap.h"
-#else
-#include <a.out.h>
-#endif
-#ifndef N_MAGIC
-#ifdef COFF_FORMAT
-#define N_MAGIC(exec) ((exec).magic)
-#else
-#define N_MAGIC(exec) ((exec).a_magic)
-#endif
-#endif
-#include <signal.h>
-#include <sys/param.h>
-#include <sys/dir.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-
-#ifdef UMAX_CORE
-#include <sys/ptrace.h>
-#else
-#include <sys/user.h>
-#endif
-
-#ifndef N_TXTADDR
-#define N_TXTADDR(hdr) 0
-#endif /* no N_TXTADDR */
-
-#ifndef N_DATADDR
-#define N_DATADDR(hdr) hdr.a_text
-#endif /* no N_DATADDR */
-
-#ifndef COFF_FORMAT
-#ifndef AOUTHDR
-#define AOUTHDR struct exec
-#endif
-#endif
-
-extern char *sys_siglist[];
-
-extern core_file_command (), exec_file_command ();
-
-/* Hook for `exec_file_command' command to call. */
-
-void (*exec_file_display_hook) ();
-
-/* File names of core file and executable file. */
-
-char *corefile;
-char *execfile;
-
-/* Descriptors on which core file and executable file are open.
- Note that the execchan is closed when an inferior is created
- and reopened if the inferior dies or is killed. */
-
-int corechan;
-int execchan;
-
-/* Last modification time of executable file.
- Also used in source.c to compare against mtime of a source file. */
-
-int exec_mtime;
-
-/* Virtual addresses of bounds of the two areas of memory in the core file. */
-
-CORE_ADDR data_start;
-CORE_ADDR data_end;
-CORE_ADDR stack_start;
-CORE_ADDR stack_end;
-
-#if defined (REG_STACK_SEGMENT)
-/* Start and end of the register stack segment. */
-CORE_ADDR reg_stack_start;
-CORE_ADDR reg_stack_end;
-#endif /* REG_STACK_SEGMENT */
-
-/* Virtual addresses of bounds of two areas of memory in the exec file.
- Note that the data area in the exec file is used only when there is no core file. */
-
-CORE_ADDR text_start;
-CORE_ADDR text_end;
-
-CORE_ADDR exec_data_start;
-CORE_ADDR exec_data_end;
-
-/* Offset within executable file of start of text area data. */
-
-int text_offset;
-
-/* Offset within executable file of start of data area data. */
-
-int exec_data_offset;
-
-/* Offset within core file of start of data area data. */
-
-int data_offset;
-
-/* Offset within core file of start of stack area data. */
-
-int stack_offset;
-
-#ifdef COFF_FORMAT
-/* various coff data structures */
-
-FILHDR file_hdr;
-SCNHDR text_hdr;
-SCNHDR data_hdr;
-
-#endif /* not COFF_FORMAT */
-
-/* a.out header saved in core file. */
-
-AOUTHDR core_aouthdr;
-
-/* a.out header of exec file. */
-
-AOUTHDR exec_aouthdr;
-
-void validate_files ();
-unsigned int register_addr ();
-
-/* 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 ()
-{
- if (execchan >= 0)
- close (execchan);
- execchan = -1;
-}
-
-void
-reopen_exec_file ()
-{
- if (execchan < 0 && execfile != 0)
- {
- char *filename = concat (execfile, "", "");
- exec_file_command (filename, 0);
- free (filename);
- }
-}
-
-/* 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 (execfile != 0 && corefile != 0)
- {
- struct stat st_core;
-
- if (fstat (corechan, &st_core) < 0)
- /* It might be a good idea to print an error message.
- On the other hand, if the user tries to *do* anything with
- the core file, (s)he'll find out soon enough. */
- return;
-
- if (N_MAGIC (core_aouthdr) != 0
- && bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
- printf ("Warning: core file does not match specified executable file.\n");
- else if (exec_mtime > st_core.st_mtime) {
-#ifdef KERNELDEBUG
- extern int kernel_debugging;
- if (!kernel_debugging)
-#endif
- 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 (err && execfile == 0)
- error ("No executable file specified.\n\
-Use the \"exec-file\" and \"symbol-file\" commands.");
- return execfile;
-}
-
-int
-have_core_file_p ()
-{
- return corefile != 0;
-}
-
-static void
-files_info ()
-{
- char *symfile;
- extern char *get_sym_file ();
-
- if (execfile)
- printf ("Executable file \"%s\".\n", execfile);
- else
- printf ("No executable file\n");
- if (corefile == 0)
- printf ("No core dump file\n");
- else
- printf ("Core dump file \"%s\".\n", corefile);
-
- if (have_inferior_p ())
- printf ("Using the running image of the program, rather than these files.\n");
-
- symfile = get_sym_file ();
- if (symfile != 0)
- printf ("Symbols from \"%s\".\n", symfile);
-
-#ifdef FILES_INFO_HOOK
- if (FILES_INFO_HOOK ())
- return;
-#endif
-
- if (! have_inferior_p ())
- {
- if (execfile)
- {
- printf ("Text segment in executable from 0x%x to 0x%x.\n",
- text_start, text_end);
- printf ("Data segment in executable from 0x%x to 0x%x.\n",
- exec_data_start, exec_data_end);
- if (corefile)
- printf ("(But since we have a core file, we're using...)\n");
- }
- if (corefile)
- {
- printf ("Data segment in core file from 0x%x to 0x%x.\n",
- data_start, data_end);
- printf ("Stack segment in core file from 0x%x to 0x%x.\n",
- stack_start, stack_end);
- }
- }
-}
-
-/* Read "memory data" from core file and/or executable file.
- Returns zero if successful, 1 if xfer_core_file failed, errno value if
- ptrace failed. */
-
-int
-read_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
-{
- if (len == 0)
- return 0;
-
- if (have_inferior_p ())
- {
- if (remote_debugging)
- return remote_read_inferior_memory (memaddr, myaddr, len);
- else
- return read_inferior_memory (memaddr, myaddr, len);
- }
- else
- return xfer_core_file (memaddr, myaddr, len);
-}
-
-/* Write LEN bytes of data starting at address MYADDR
- into debugged program memory at address MEMADDR.
- Returns zero if successful, or an errno value if ptrace failed. */
-
-int
-write_memory (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
-{
- if (have_inferior_p ())
- {
- if (remote_debugging)
- return remote_write_inferior_memory (memaddr, myaddr, len);
- else
- return write_inferior_memory (memaddr, myaddr, len);
- }
- else
- error ("Can write memory only when program being debugged is running.");
-}
-
-#ifndef XFER_CORE_FILE
-int (*core_file_hook)(); /* hook to handle special core files like
- like /dev/mem and crash dumps */
-
-/* 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, 1 if not. */
-
-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;
-
- if (core_file_hook)
- return ((*core_file_hook)(memaddr, myaddr, len));
-
- 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 are equal. */
- else if (memaddr >= stack_start && memaddr < stack_end)
- {
- i = min (len, stack_end - memaddr);
- fileptr = memaddr - stack_start + stack_offset;
- xferfile = &corefile;
- xferchan = corechan;
- }
-#ifdef REG_STACK_SEGMENT
- /* Pyramids have an extra segment in the virtual address space
- for the (control) stack of register-window frames */
- 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;
- xferfile = &corefile;
- xferchan = corechan;
- }
-#endif /* REG_STACK_SEGMENT */
-
- 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)
- {
- i = min (len, text_end - memaddr);
- fileptr = memaddr - 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)
- {
- /* Since there is nothing at higher addresses than data
- (without a core file or an inferior, there is no
- stack, set i to do the rest of the operation now. */
- i = len;
- }
-#ifdef REG_STACK_SEGMENT
- else if (memaddr >= reg_stack_end && reg_stack_end != 0)
- {
- i = min (len, reg_stack_start - memaddr);
- }
- else if (memaddr >= stack_end && memaddr < reg_stack_start)
-#else /* no REG_STACK_SEGMENT. */
- else if (memaddr >= stack_end && stack_end != 0)
-#endif /* no REG_STACK_SEGMENT. */
- {
- /* Since there is nothing at higher addresses than
- the stack, set i to do the rest of the operation now. */
- i = len;
- }
- 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 == -1)
- 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 = 1;
- }
-
- memaddr += i;
- myaddr += i;
- len -= i;
- }
- return returnval;
-}
-#endif /* XFER_CORE_FILE */
-
-/* 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;
-}
-
-#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 */
-
-void
-_initialize_core()
-{
- corechan = -1;
- execchan = -1;
- corefile = 0;
- execfile = 0;
- exec_file_display_hook = 0;
-
- text_start = 0;
- text_end = 0;
- data_start = 0;
- data_end = 0;
- exec_data_start = 0;
- exec_data_end = 0;
- stack_start = STACK_END_ADDR;
- stack_end = STACK_END_ADDR;
-
- 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.");
- 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_info ("files", files_info, "Names of files being debugged.");
-}
-
diff --git a/gnu/usr.bin/gdb/cplus-dem.c b/gnu/usr.bin/gdb/cplus-dem.c
deleted file mode 100644
index 8ea9c8bb55ac..000000000000
--- a/gnu/usr.bin/gdb/cplus-dem.c
+++ /dev/null
@@ -1,996 +0,0 @@
-/* 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 nounderscore 1 /* define this is names don't start with _ */
-
-#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);
-#else
-extern char *xmalloc ();
-extern char *xrealloc ();
-#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 ();
-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 ();
-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/gnu/usr.bin/gdb/dbxread.c b/gnu/usr.bin/gdb/dbxread.c
deleted file mode 100644
index 7a25665536a4..000000000000
--- a/gnu/usr.bin/gdb/dbxread.c
+++ /dev/null
@@ -1,5727 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)dbxread.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* Read dbx symbol tables and convert to internal format, 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. */
-
-/* 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()).
- 2. Full read-in of symbols. (psymtab_to_symtab()). This happens
- when a symbol in a file for which symbols have not yet been
- read in is referenced.
- 2a. The "add-file" command. Similar to #2. */
-
-#include <stdio.h>
-#include "defs.h"
-#include "param.h"
-
-#ifdef READ_DBX_FORMAT
-
-#ifdef USG
-#include <sys/types.h>
-#include <fcntl.h>
-#define L_SET 0
-#define L_INCR 1
-#endif
-
-#ifdef COFF_ENCAPSULATE
-#include "a.out.encap.h"
-#include "stab.gnu.h"
-#else
-#include <a.out.h>
-#include <stab.h>
-#endif
-#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 */
-
-#ifndef __GNU_STAB__
-
-/* Line number for the data section. This is to be used to describe
- the source location of a variable declaration. */
-#ifndef N_DSLINE
-#define N_DSLINE (N_SLINE+N_DATA-N_TEXT)
-#endif
-
-/* Line number for the bss section. This is to be used to describe
- the source location of a variable declaration. */
-#ifndef N_BSLINE
-#define N_BSLINE (N_SLINE+N_BSS-N_TEXT)
-#endif
-
-#endif /* not __GNU_STAB__ */
-#endif /* NO_GNU_STABS */
-
-#include <obstack.h>
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-
-#include "symtab.h"
-
-#ifndef COFF_FORMAT
-#ifndef AOUTHDR
-#define AOUTHDR struct exec
-#endif
-#endif
-
-static void add_symbol_to_list ();
-static void read_dbx_symtab ();
-static void process_one_symbol ();
-static void free_all_psymbols ();
-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 read_huge_number ();
-static void finish_block ();
-static struct blockvector *make_blockvector ();
-static struct symbol *define_symbol ();
-static void start_subfile ();
-static int hashname ();
-static void hash_symsegs ();
-static struct pending *copy_pending ();
-static void fix_common_block ();
-
-static void add_undefined_type ();
-static void cleanup_undefined_types ();
-
-extern char *index();
-
-extern struct symtab *read_symsegs ();
-extern void free_all_symtabs ();
-extern void free_all_psymtabs ();
-extern void free_inclink_symtabs ();
-
-/* C++ */
-static struct type **read_args ();
-
-/* Macro to determine which symbols to ignore when reading the first symbol
- of a file. Some machines override this definition. */
-#ifdef N_NSYMS
-#ifndef IGNORE_SYMBOL
-/* This code is used on Ultrix systems. Ignore it */
-#define IGNORE_SYMBOL(type) (type == N_NSYMS)
-#endif
-#else
-#ifndef IGNORE_SYMBOL
-/* Don't ignore any symbols. */
-#define IGNORE_SYMBOL(type) (0)
-#endif
-#endif /* not N_NSYMS */
-
-/* Macro for number of symbol table entries (in usual a.out format).
- Some machines override this definition. */
-#ifndef NUMBER_OF_SYMBOLS
-#ifdef COFF_HEADER
-#define NUMBER_OF_SYMBOLS \
- ((COFF_HEADER(hdr) ? hdr.coffhdr.filehdr.f_nsyms : hdr.a_syms) / \
- sizeof (struct nlist))
-#else
-#define NUMBER_OF_SYMBOLS (hdr.a_syms / sizeof (struct nlist))
-#endif
-#endif
-
-/* Macro for file-offset of symbol table (in usual a.out format). */
-#ifndef SYMBOL_TABLE_OFFSET
-#define SYMBOL_TABLE_OFFSET N_SYMOFF (hdr)
-#endif
-
-/* Macro for file-offset of string table (in usual a.out format). */
-#ifndef STRING_TABLE_OFFSET
-#define STRING_TABLE_OFFSET (N_SYMOFF (hdr) + hdr.a_syms)
-#endif
-
-/* Macro to store the length of the string table data in INTO. */
-#ifndef READ_STRING_TABLE_SIZE
-#define READ_STRING_TABLE_SIZE(INTO) \
-{ val = myread (desc, &INTO, sizeof INTO); \
- if (val < 0) perror_with_name (name); }
-#endif
-
-/* Macro to declare variables to hold the file's header data. */
-#ifndef DECLARE_FILE_HEADERS
-#define DECLARE_FILE_HEADERS AOUTHDR hdr
-#endif
-
-/* Macro to read the header data from descriptor DESC and validate it.
- NAME is the file name, for error messages. */
-#ifndef READ_FILE_HEADERS
-#ifdef HEADER_SEEK_FD
-#define READ_FILE_HEADERS(DESC, NAME) \
-{ HEADER_SEEK_FD (DESC); \
- 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); }
-#else
-#define READ_FILE_HEADERS(DESC, NAME) \
-{ 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); }
-#endif
-#endif
-
-/* Non-zero if this is an object (.o) file, rather than an executable.
- Distinguishing between the two is rarely necessary (and seems like
- a hack, but there is no other way to do ADDR_OF_TEXT_SEGMENT
- right for SunOS). */
-#if !defined (IS_OBJECT_FILE)
-/* This will not work
- if someone decides to make ld preserve relocation info. */
-#define IS_OBJECT_FILE (hdr.a_trsize != 0)
-#endif
-
-/* Macro for size of text segment */
-#ifndef SIZE_OF_TEXT_SEGMENT
-#define SIZE_OF_TEXT_SEGMENT hdr.a_text
-#endif
-
-/* Get the address in debugged memory of the start
- of the text segment. */
-#if !defined (ADDR_OF_TEXT_SEGMENT)
-#if defined (N_TXTADDR)
-#define ADDR_OF_TEXT_SEGMENT (IS_OBJECT_FILE ? 0 : N_TXTADDR (hdr))
-#else /* no N_TXTADDR */
-#define ADDR_OF_TEXT_SEGMENT 0
-#endif /* no N_TXTADDR */
-#endif /* no ADDR_OF_TEXT_SEGMENT */
-
-/* Macro to get entry point from headers. */
-#ifndef ENTRY_POINT
-#define ENTRY_POINT hdr.a_entry
-#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
-
-/* Nonzero means give verbose info on gdb action. From main.c. */
-extern int info_verbose;
-
-/* Chain of symtabs made from reading the file's symsegs.
- These symtabs do not go into symtab_list themselves,
- but the information is copied from them when appropriate
- to make the symtabs that will exist permanently. */
-
-static struct symtab *symseg_chain;
-
-/* Symseg symbol table for the file whose data we are now processing.
- It is one of those in symseg_chain. Or 0, for a compilation that
- has no symseg. */
-
-static struct symtab *current_symseg;
-
-/* 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;
-
-/* End of the text segment of the executable file,
- as found in the symbol _etext. */
-
-static CORE_ADDR end_of_text_addr;
-
-/* 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;
- 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 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, 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;
- 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 */
-
-/* File name symbols were loaded from. */
-
-static char *symfile;
-
-/* Low and high symbol values (inclusive) for the global variable
- entries in the symbol file. */
-
-static int first_global_sym, last_global_sym;
-
-/* Structures with which to manage partial symbol allocation. */
-
-struct psymbol_allocation_list global_psymbols, static_psymbols;
-
-/* 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;
-
- /* Setup a define to deal cleanly with the underscore problem */
-
-#ifdef NAMES_HAVE_UNDERSCORE
-#define HASH_OFFSET 1
-#else
-#define HASH_OFFSET 0
-#endif
-
-#if 0
-/* I'm not sure why this is here. To debug bugs which cause
- an infinite loop of allocations, I suppose. In any event,
- dumping core when out of memory isn't usually right. */
-static int
-xxmalloc (n)
-{
- int v = malloc (n);
- if (v == 0)
- {
- fprintf (stderr, "Virtual memory exhausted.\n");
- abort ();
- }
- return v;
-}
-#else /* not 0 */
-#define xxmalloc xmalloc
-#endif /* not 0 */
-
-/* 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. */
-
-static 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. */
-
-static 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;
-}
-
-/* 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;
-
-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;
-
-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;
-
-/* At the start of reading dbx symbols, allocate our tables. */
-
-static void
-init_header_files ()
-{
- n_allocated_header_files = 10;
- header_files = (struct header_file *) xxmalloc (10 * sizeof (struct header_file));
- n_header_files = 0;
-
- n_allocated_this_object_header_files = 10;
- this_object_header_files = (int *) xxmalloc (10 * sizeof (int));
-}
-
-/* At the end of reading dbx symbols, free our tables. */
-
-static void
-free_header_files ()
-{
- register int i;
- for (i = 0; i < n_header_files; i++)
- free (header_files[i].name);
- if (header_files) free (header_files);
- if (this_object_header_files)
- free (this_object_header_files);
-}
-
-/* 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;
- register struct header_file *p = header_files;
- header_file_prev_index = -1;
-
-#if 0
- /* This code was used before I knew about the instance codes.
- My first hypothesis is that it is not necessary now
- that instance codes are handled. */
-
- /* Has this header file a previous definition?
- If so, make a new entry anyway so that this use in this source file
- gets a separate entry. Later source files get the old entry.
- Record here the index of the old entry, so that any type indices
- not previously defined can get defined in the old entry as
- well as in the new one. */
-
- for (i = 0; i < n_header_files; i++)
- if (!strcmp (p[i].name, name))
- {
- header_file_prev_index = i;
- }
-
-#endif
-
- /* 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 **) xxmalloc (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;
-
- if (real_filenum >= n_header_files)
- abort ();
-
- 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];
- }
-}
-
-/* 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
-
-/* 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 *) xxmalloc (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. */
-
-static void
-really_free_pendings ()
-{
- struct pending *next, *next1;
- struct pending_block *bnext, *bnext1;
-
- for (next = free_pendings; next; next = next1)
- {
- next1 = next->next;
- free (next);
- }
- free_pendings = 0;
-
- for (bnext = pending_blocks; bnext; bnext = bnext1)
- {
- bnext1 = bnext->next;
- free (bnext);
- }
- 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);
-
- 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)
- 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, *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;
-
-#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;
-
- return blockvector;
-}
-
-/* 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;
-}
-
-/* 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, start_addr)
- char *name;
- CORE_ADDR start_addr;
-{
- register struct symtab *s;
-
- 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 *) xxmalloc (10 * sizeof (struct context_stack));
- context_stack_size = 10;
- context_stack_depth = 0;
-
- new_object_header_files ();
-
- for (s = symseg_chain; s; s = s->next)
- if (s->ldsymoff == symnum * sizeof (struct nlist))
- break;
- current_symseg = s;
- if (s != 0)
- return;
-
- type_vector_length = 160;
- type_vector = (struct typevector *)
- xxmalloc (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);
-
-#if 0 /* This is now set at the beginning of read_ofile_symtab */
- /* Set default for compiler to pcc; assume that we aren't processing
- a gcc compiled file until proved otherwise. */
-
- processing_gcc_compilation = 0;
-#endif
-}
-
-/* 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)
- char *name;
-{
- 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 *)
- xxmalloc (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 *) xxmalloc (sizeof (struct subfile));
- subfile->next = subfiles;
- subfile->name = savestring (name, strlen (name));
- 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;
-
- if (current_symseg != 0)
- {
- last_source_file = 0;
- current_symseg = 0;
- return;
- }
-
- /* 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 *) xxmalloc (sizeof (struct symtab));
- symtab->free_ptr = 0;
-
- /* Fill in its components. */
- symtab->blockvector = blockvector;
- type_vector->length = type_vector_length;
- symtab->typevector = type_vector;
- symtab->free_code = free_linetable;
- if (subfile->next == 0)
- symtab->free_ptr = (char *) type_vector;
-
- symtab->filename = subfile->name;
- 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)));
- symtab->nlines = 0;
- symtab->line_charpos = 0;
-
- /* 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;
-}
-
-#ifdef N_BINCL
-
-/* 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 *) xxmalloc (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;
-}
-#endif /* Have N_BINCL */
-
-/* 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;
-
-static void
-init_misc_functions ()
-{
- misc_count = 0;
- misc_bunch = 0;
- misc_bunch_index = MISC_BUNCH_SIZE;
-}
-
-static void
-record_misc_function (name, address, type)
- char *name;
- CORE_ADDR address;
- int type;
-{
- register struct misc_bunch *new;
- register unsigned char mtype;
-
- if (misc_bunch_index == MISC_BUNCH_SIZE)
- {
- new = (struct misc_bunch *) xxmalloc (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;
- switch (type &~ N_EXT)
- {
- case N_TEXT: mtype = mf_text; break;
- case N_DATA: mtype = mf_data; break;
- case N_BSS: mtype = mf_bss; break;
- case N_ABS: mtype = mf_abs; break;
-#ifdef N_SETV
- case N_SETV: mtype = mf_data; break;
-#endif
- default: mtype = mf_unknown; break;
- }
- misc_bunch->contents[misc_bunch_index].type = mtype;
- 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;
-}
-
-static void
-discard_misc_bunches ()
-{
- 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. */
-static void
-condense_misc_bunches (inclink)
- int inclink;
-{
- register int i, j;
- register struct misc_bunch *bunch;
-#ifdef NAMES_HAVE_UNDERSCORE
- int offset = 1;
-#else
- int offset = 0;
-#endif
-
- 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 *)
- xxmalloc (misc_count * sizeof (struct misc_function));
- j = 0;
- }
-
- bunch = misc_bunch;
- while (bunch)
- {
- for (i = 0; i < misc_bunch_index; i++)
- {
- misc_function_vector[j] = bunch->contents[i];
- misc_function_vector[j].name
- = obconcat (misc_function_vector[j].name
- + (misc_function_vector[j].name[0] == '_' ? offset : 0),
- "", "");
- j++;
- }
- bunch = bunch->next;
- misc_bunch_index = MISC_BUNCH_SIZE;
- }
-
- if (inclink)
- misc_function_count += misc_count;
- else
- misc_function_count = j;
-
- /* Sort the misc functions by address. */
-
- qsort (misc_function_vector, misc_function_count,
- sizeof (struct misc_function),
- compare_misc_functions);
-
- /* (re)build the hash table (positions changed during the sort) */
-
- for (i = 0; i < MISC_FUNC_HASH_SIZE; ++i)
- misc_function_hash_tab[i] = -1;
- for (i = 0; i < misc_function_count; ++i)
- {
- j = hash_symbol(misc_function_vector[i].name) & (MISC_FUNC_HASH_SIZE - 1);
- misc_function_vector[i].next = misc_function_hash_tab[j];
- misc_function_hash_tab[j] = i;
- }
-}
-
-/* Call sort_syms to sort alphabetically
- the symbols of each block of each symtab. */
-
-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));
-}
-
-static void sort_symtab_syms ();
-
-static void
-sort_syms ()
-{
- register struct symtab *s;
-
- for (s = symtab_list; s; s = s->next)
- sort_symtab_syms (s);
-}
-
-static 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;
-
- /* Note that 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). We do this by a
- correct compare in compare_symbols, and by the reversal of the
- symbols if we don't sort. This works as long as a register debug
- symbol always comes after a parameter debug symbol. */
-
- /* This is no longer necessary; lookup_block_symbol now always
- prefers some other declaration over a parameter declaration. We
- still sort the thing (that is necessary), but we don't reverse it
- if we shouldn't sort it. */
-
- for (i = 0; i < nbl; i++)
- {
- b = BLOCKVECTOR_BLOCK (bv, i);
- if (BLOCK_SHOULD_SORT (b))
- qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
- sizeof (struct symbol *), compare_symbols);
- }
-}
-
-
-extern struct symtab *psymtab_to_symtab ();
-
-/* The entry point. */
-static CORE_ADDR entry_point;
-
-static char *symfile_string_table;
-static int symfile_string_table_size;
-
-/* 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;
-{
- register int desc;
- DECLARE_FILE_HEADERS;
- struct nlist *nlist;
-
- /* The string table. */
- char *stringtab;
-
- /* The size of the string table (buffer is a bizarre name...). */
- long buffer;
-
- register int val;
- extern void close ();
- struct cleanup *old_chain;
- struct symtab *symseg;
- struct stat statbuf;
-
- dont_repeat ();
-
- if (name == 0)
- {
- if ((symtab_list || partial_symtab_list)
- && from_tty
- && !query ("Discard symbol table? ", 0))
- error ("Not confirmed.");
- if (symfile)
- free (symfile);
- symfile = 0;
- free_all_symtabs ();
- free_all_psymtabs ();
- return;
- }
-
- name = tilde_expand (name);
- make_cleanup (free, name);
-
- if ((symtab_list || partial_symtab_list)
- && !query ("Load new symbol table from \"%s\"? ", name))
- error ("Not confirmed.");
-
- {
- 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);
-
- READ_FILE_HEADERS (desc, name);
-
- entry_point = ENTRY_POINT;
-
- if (NUMBER_OF_SYMBOLS == 0)
- {
- if (symfile)
- free (symfile);
- symfile = 0;
- free_all_symtabs ();
- free_all_psymtabs ();
- printf ("%s has no symbol-table; symbols discarded.\n", name);
- fflush (stdout);
- do_cleanups (old_chain);
- return;
- }
-
- printf ("Reading symbol data from %s...", name);
- fflush (stdout);
-
- /* Now read the string table, all at once. */
- val = lseek (desc, STRING_TABLE_OFFSET, 0);
- if (val < 0)
- perror_with_name (name);
- if (stat (name, &statbuf) == -1)
- perror_with_name (name);
- READ_STRING_TABLE_SIZE (buffer);
- if (buffer >= 0 && buffer < statbuf.st_size)
- {
- /* This should speed things up without consuming much
- extra memory (because probably little of the space is going
- to be reused anyway, whether in data or stack space).
-
- A quick test (running GDB on itself and setting 9 breakpoints
- in different files) showed that memory usage was almost
- identical for the two cases. */
-#if 0
-#ifdef BROKEN_LARGE_ALLOCA
- stringtab = (char *) xmalloc (buffer);
- make_cleanup (free, stringtab);
-#else
- stringtab = (char *) alloca (buffer);
-#endif
-#endif
- stringtab = (char *) xmalloc (buffer);
- symfile_string_table = stringtab;
- symfile_string_table_size = buffer;
- }
- else
- stringtab = NULL;
- if (stringtab == NULL)
- error ("ridiculous string table size: %d bytes", buffer);
-
- /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
- Occaisionally, it won't. */
- val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
- if (val < 0)
- perror_with_name (name);
- val = myread (desc, stringtab, buffer);
- if (val < 0)
- perror_with_name (name);
-
- /* Throw away the old symbol table. */
-
- if (symfile)
- free (symfile);
- symfile = 0;
- free_all_symtabs ();
- free_all_psymtabs ();
-
- /* Empty the hash table of global syms looking for values. */
- bzero (global_sym_chain, sizeof global_sym_chain);
-
- /* Symsegs are no longer supported by GDB. Setting symseg_chain to
- 0 is easier than finding all the symseg code and eliminating it. */
- symseg_chain = 0;
-
- /* Position to read the symbol table. Do not read it all at once. */
- val = lseek (desc, SYMBOL_TABLE_OFFSET, 0);
- if (val < 0)
- perror_with_name (name);
-
- /* 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. */
- free_header_files ();
- init_header_files ();
-
- init_misc_functions ();
- make_cleanup (discard_misc_bunches, 0);
-
- free_pendings = 0;
- pending_blocks = 0;
- file_symbols = 0;
- global_symbols = 0;
- make_cleanup (really_free_pendings, 0);
-
- /* Now that the symbol table data of the executable file are all in core,
- process them and define symbols accordingly. Closes desc. */
-
- read_dbx_symtab (desc, stringtab, buffer, NUMBER_OF_SYMBOLS, 0,
- ADDR_OF_TEXT_SEGMENT, SIZE_OF_TEXT_SEGMENT);
-
- /* Go over the misc functions 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;
-
- /* Make a default for file to list. */
-
- symfile = savestring (name, strlen (name));
-
- /* 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 */
-
- do_cleanups (old_chain); /* Descriptor closed here */
-
- /* Free the symtabs made by read_symsegs, but not their contents,
- which have been copied into symtabs on symtab_list. */
- while (symseg_chain)
- {
- register struct symtab *s = symseg_chain->next;
- free (symseg_chain);
- symseg_chain = s;
- }
-
- if (!partial_symtab_list)
- printf ("\n(no debugging symbols found)...");
-
- printf ("done.\n");
- fflush (stdout);
-}
-
-/* Return name of file symbols were loaded from, or 0 if none.. */
-
-char *
-get_sym_file ()
-{
- return symfile;
-}
-
-/* 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 of the string table
- of the object file we are reading (as copied into core). */
-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)
- error ("error or end of file reading symbol table");
- symbuf_end = nbytes / sizeof (struct nlist);
- symbuf_idx = 0;
- return 1;
-}
-
-/* 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++;
- return symbuf[symbuf_idx++].n_un.n_strx + stringtab_global;
-}
-
-/*
- * Initializes storage for all of the partial symbols that will be
- * created by read_dbx_symtab and subsidiaries.
- */
-void
-init_psymbol_list (total_symbols)
- int total_symbols;
-{
- /* 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 (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 add_psymtab_dependency ();
-static void end_psymtab();
-
-static int
-compare_psymbols (s1, s2)
- register struct partial_symbol *s1, *s2;
-{
- register char
- *st1 = SYMBOL_NAME (s1),
- *st2 = SYMBOL_NAME (s2);
- register int i;
-
- if (st1[0] - st2[0])
- return (st1[0] - st2[0]);
- if (st1[1] - st2[1])
- return (st1[1] - st2[1]);
- if (i = strcmp(st1, st2))
- return (i);
- /* Next comparison implements policy that used to be in lookup_symbol:
- * it would search psymtabs in psymtab_list order (reverse order of
- * declaration) & take first occurance of symbol it found. So, we
- * collate duplicate names in reverse psymtab order. */
- return (s2->pst - s1->pst);
-}
-
-/* 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.
-
- I have no idea whether or not this routine should be setup to deal
- with inclinks. It seems reasonable to me that they be dealt with
- standardly, so I am not going to make a strong effort to deal with
- them here.
- */
-
-static void
-read_dbx_symtab (desc, stringtab, stringtab_size, nlistlen, inclink,
- text_addr, text_size)
- int desc;
- register char *stringtab;
- register long stringtab_size;
- register int nlistlen;
- int inclink;
- unsigned text_addr;
- int text_size;
-{
- register struct nlist *bufp;
- register char *namestring;
- register struct partial_symbol *psym;
- register struct psymbol_allocation_list *psymbol_struct;
-
- int nsl;
- int past_first_source_file = 0;
- CORE_ADDR last_o_file_start = 0;
- char *last_o_file_name = "*bogus*";
- struct cleanup *old_chain;
- char *p;
- enum namespace ns;
- enum address_class class;
-
-#ifdef PROFILE_TYPES
- int i;
- int profile_types [256];
- int strcmp_called = 0;
- int autovars = 0;
- int global_funs = 0;
-#endif
-
- /* 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;
-
-#ifdef PROFILE_TYPES
- for (i = 0; i < 256; i++)
- profile_types[i] = 0;
-#endif
-
- 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 *));
-
- old_chain = make_cleanup (free_all_psymtabs, 0);
-
- /* Init bincl list */
- init_bincl_list (20);
- make_cleanup (free_bincl_list, 0);
-
- /* Setup global partial symbol list */
- init_psymbol_list (nlistlen);
-
- last_source_file = 0;
-
-#ifdef END_OF_TEXT_DEFAULT
- end_of_text_addr = END_OF_TEXT_DEFAULT;
-#else
- end_of_text_addr = text_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++];
-
-#ifdef PROFILE_TYPES
- profile_types[bufp->n_type]++;
-#endif
-
- /*
- * Special case to speed up readin.
- */
- if (bufp->n_type == N_SLINE) continue;
-
- /* Ok. There is a lot of code duplicated in the rest of this
- switch statiement (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 index.
- *) 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. */
-#define SET_NAMESTRING()\
- 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
-
-#define ADD_PSYMBOL_TO_LIST(NAME, NAMELENGTH, NAMESPACE, CLASS, LIST, VALUE)\
- 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); \
- SYMBOL_VALUE (psym) = (VALUE); \
- } while (0);
-
-
- switch (bufp->n_type)
- {
- /*
- * Standard, non-debugger, symbols
- */
-
- case N_TEXT | N_EXT:
- /* Catch etext */
-
- SET_NAMESTRING();
-
- if (namestring[6] == '\0' && namestring[5] == 't'
- && namestring[4] == 'x' && namestring[3] == 'e'
- && namestring[2] == 't' && namestring[1] == 'e'
- && namestring[0] == '_')
- end_of_text_addr = bufp->n_value;
-
- /* Figure out beginning and end of global linker symbol
- section and put non-debugger specified symbols on
- tmp_symchain */
-
- last_global_sym = symnum;
- if (!first_global_sym) first_global_sym = symnum;
-
- record_misc_function (namestring, bufp->n_value,
- bufp->n_type); /* Always */
-
- continue;
-
-#ifdef N_NBTEXT
- case N_NBTEXT | N_EXT:
-#endif
-#ifdef N_NBDATA
- case N_NBDATA | N_EXT:
-#endif
-#ifdef N_NBBSS
- case N_NBBSS | N_EXT:
-#endif
-#ifdef N_SETV
- case N_SETV | N_EXT:
-#endif
- case N_ABS | N_EXT:
- case N_DATA | N_EXT:
- case N_BSS | N_EXT:
- /* Figure out beginning and end of global linker symbol
- section and put non-debugger specified symbols on
- tmp_symchain */
-
- SET_NAMESTRING();
-
- last_global_sym = symnum;
- if (!first_global_sym) first_global_sym = symnum;
-
- /* Not really a function here, but... */
- record_misc_function (namestring, bufp->n_value,
- bufp->n_type); /* Always */
-
- continue;
-
-#ifdef N_NBTEXT
- case N_NBTEXT:
-#endif
-
- /* 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:
- 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)
- {
- startup_file_start = last_o_file_start;
- startup_file_end = bufp->n_value;
- }
- if (past_first_source_file && pst)
- {
- 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;
- last_o_file_name = namestring;
- nsl = strlen(namestring);
- if (namestring[nsl-2] == '.' && namestring[nsl-1] == 'o')
- namestring[nsl-2] = 0;
- }
- else if (strcmp(namestring, "gcc_compiled."))
- {
- if (*namestring == '_')
- ++namestring;
- namestring = obconcat(last_o_file_name, ":", namestring);
- last_global_sym = symnum;
- if (!first_global_sym)
- first_global_sym = symnum;
- record_misc_function(namestring, bufp->n_value, bufp->n_type);
- }
- continue;
-
- case N_ABS:
- case N_DATA:
- case N_BSS:
- SET_NAMESTRING();
- if (*namestring == '_')
- ++namestring;
- namestring = obconcat(last_o_file_name, ":", namestring);
- last_global_sym = symnum;
- if (!first_global_sym)
- first_global_sym = symnum;
- record_misc_function(namestring, bufp->n_value, bufp->n_type);
- continue;
-
- case N_UNDF:
- case N_UNDF | N_EXT:
-#ifdef N_NBDATA
- case N_NBDATA:
-#endif
-#ifdef N_NBBSS
- case N_NBBSS:
-#endif
-
- /* Keep going . . .*/
-
- /*
- * Special symbol types for GNU
- */
-#ifdef N_INDR
- case N_INDR:
- case N_INDR | N_EXT:
-#endif
-#ifdef N_SETA
- 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:
-#endif
- continue;
-
- /*
- * Debugger symbols
- */
-
- case N_SO:
- /* End the current partial symtab and start a new one */
-
- SET_NAMESTRING();
-
- if (pst && past_first_source_file)
- {
- 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;
-
- pst = start_psymtab (namestring, bufp->n_value,
- symnum * sizeof (struct nlist),
- global_psymbols.next, static_psymbols.next);
-
- continue;
-
-#ifdef N_BINCL
- 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 return */
-
- 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;
-#endif
-
- 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 *) index (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);
- 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. */
-
- /* 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:
-#ifdef PROFILE_TYPES
- if (isalpha(p[1]))
- printf ("Funny...LSYM with a letter that isn't a type\n");
- autovars++;
-#endif
- /* 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:
-#if 0
- /* This special-casing of N_FUN is just wrong; N_FUN
- does not mean "function"; it means "text segment".
- So N_FUN can go with 'V', etc. as well as 'f' or 'F'. */
-
- SET_NAMESTRING();
-
- p = (char *) index (namestring, ':');
-
- if (!p || p[1] == 'F') continue;
-
-#ifdef PROFILE_TYPES
- if (p[1] != 'f')
- printf ("Funny...FUN with a letter that isn't 'F' or 'f'.\n");
- global_funs++;
-#endif
-
- ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
- VAR_NAMESPACE, LOC_BLOCK,
- static_psymbols, bufp->n_value);
-
- continue;
-#endif /* 0 */
- case N_GSYM: /* Global (extern) variable; can be
- data or bss (sigh). */
- case N_STSYM: /* Data seg var -- static */
- case N_LCSYM: /* BSS " */
-
- /* 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. */
-#ifdef N_M2C
- case N_M2C: /* I suspect that I can ignore this here. */
- case N_SCOPE: /* Same. */
-#endif
-
- SET_NAMESTRING();
-
- p = (char *) index (namestring, ':');
- if (!p)
- continue; /* Not a debugging symbol. */
-
- process_symbol_for_psymtab:
-
- /* 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':
- ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
- VAR_NAMESPACE, LOC_STATIC,
- static_psymbols, bufp->n_value);
- continue;
- case 'G':
- ADD_PSYMBOL_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:
- fatal ("Internal error: Unexpected debugging symbol type '%c' at symnum %d.\n",
- p[1], symnum);
- }
-
-#ifdef N_BINCL
- 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:
-#endif
-#ifdef N_DSLINE
- case N_DSLINE:
-#endif
-#ifdef N_BSLINE
- case N_BSLINE:
-#endif
- case N_SSYM: /* Claim: Structure or union element.
- Hopefully, I can ignore this. */
- case N_ENTRY: /* Alternate entry point; can ignore. */
-#ifdef N_MAIN
- case N_MAIN: /* Can definitely ignore this. */
-#endif
- 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:
- /* These symbols aren't interesting; don't worry about them */
-
- continue;
-
- default:
- /* If we haven't found it yet, we've got problems */
-
- if (IGNORE_SYMBOL (bufp->n_type))
- continue;
-
- fatal ("Bad symbol type 0x%x encountered in gdb scan", bufp->n_type);
- }
- }
-
- /* 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;
- }
-
- /* sort the global & static symtab list so we can binary search them */
- qsort (global_psymbols.list, global_psymbols.next - global_psymbols.list,
- sizeof (struct partial_symbol), compare_psymbols);
- qsort (static_psymbols.list, static_psymbols.next - static_psymbols.list,
- sizeof (struct partial_symbol), compare_psymbols);
- free_bincl_list ();
- discard_cleanups (old_chain);
-#ifdef PROFILE_TYPES
- {
- int i, j;
-#define __define_stab(SYM, NUMBER, NAME) {NUMBER, NAME},
- static struct xyzzy {
- unsigned char symnum;
- char *name;
- } tmp_list[] = {
-#include "stab.def"
- {0x1, "eREF"},
- {0x2, "ABS"},
- {0x3, "eABS"},
- {0x4, "TEXT"},
- {0x5, "eTEXT"},
- {0x6, "DATA"},
- {0x7, "eDATA"},
- {0x8, "BSS"},
- {0x9, "eBSS"},
- {0x12, "COMM"},
- {0x13, "eCOMM"},
- {0x1f, "FN"},
- {0, "Unknown"},
-};
- for (i = 0; i < 256; i++)
- {
- for (j = 0; j < (sizeof (tmp_list) / sizeof (struct xyzzy)) - 1; j++)
- if (tmp_list[j].symnum == i)
- break;
- printf ("Symbol \"%s\" (0x%x) occured %d times.\n",
- tmp_list[j].name, i, profile_types[i]);
- }
- printf ("Auto vars (under LSYM): %d\n", autovars);
- printf ("Global funs (under FUN): %d\n", global_funs);
- }
-#endif
-}
-
-/*
- * Allocate and partially fill a partial symtab. It will be
- * completely filled at the end of the symbol list.
- */
-static struct partial_symtab *
-start_psymtab (filename, textlow, ldsymoff, global_syms, static_syms)
- char *filename;
- int 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->filename =
- (char *) obstack_alloc (psymbol_obstack,
- strlen (filename) + 1);
- strcpy (result->filename, filename);
-
- result->textlow = textlow;
- result->ldsymoff = ldsymoff;
-
- result->readin = 0;
-
- 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;
-}
-
-
-/* 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;
- int capping_text;
- struct partial_symtab **dependency_list;
- int number_dependencies;
- struct partial_symbol *capping_global, *capping_static;
-{
- int i;
- register struct partial_symbol *ps;
-
- 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->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 *));
- pst->number_of_dependencies = number_dependencies;
-
- 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->ldsymoff =
- subpst->ldsymlen =
- subpst->textlow =
- subpst->texthigh = 0;
- subpst->readin = 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->next = partial_symtab_list;
- partial_symtab_list = subpst;
- }
-
- for (ps = global_psymbols.list + pst->globals_offset;
- ps < capping_global; ++ps)
- ps->pst = pst;
- for (ps = static_psymbols.list + pst->statics_offset;
- ps < capping_static; ++ps)
- ps->pst = pst;
-
- /* Put the psymtab on the psymtab list */
- pst->next = partial_symtab_list;
- partial_symtab_list = pst;
-}
-
-
-/* Helper routines for psymtab_to_symtab. */
-static void scan_file_globals ();
-static void read_ofile_symtab ();
-
-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)
- {
- printf_filtered (" and %s...", pst->dependencies[i]->filename);
- 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, 0);
- 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. Return
- * the value of the symtab you create. Do not free the storage
- * allocated to the psymtab; it may have pointers to it.
- */
-struct symtab *
-psymtab_to_symtab(pst)
- struct partial_symtab *pst;
-{
- int desc;
- DECLARE_FILE_HEADERS;
- char *stringtab;
- struct partial_symtab **list_patch;
- int stsize, val;
- struct stat statbuf;
- struct cleanup *old_chain;
- extern void close ();
- int i;
- struct symtab *result;
- char *name = symfile; /* Some of the macros require the */
- /* variable "name" to be defined in */
- /* the context in which they execute */
- /* (Yech!) */
-
- if (!pst)
- return 0;
-
- if (pst->readin)
- {
- fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
- pst->filename);
- return 0;
- }
-
- if (!name)
- error("No symbol file currently specified; use command symbol-file");
-
- 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 */
- if (stat (name, &statbuf) < 0)
- perror_with_name (name);
- desc = open(name, O_RDONLY, 0); /* symbol_file_command
- guarrantees that the symbol file name
- will be absolute, so there is no
- need for openp */
-
- old_chain = make_cleanup (close, desc);
-
- if (desc < 0)
- error("Symbol file not readable");
-
- READ_FILE_HEADERS (desc, name);
-
-#if 0
- /* Read in the string table */
- lseek (desc, STRING_TABLE_OFFSET, L_SET);
- READ_STRING_TABLE_SIZE (stsize);
- 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)
- error ("ridiculous string table size: %d bytes", stsize);
-
- /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
- Occaisionally, it won't. */
- val = lseek (desc, STRING_TABLE_OFFSET, L_SET);
- if (val < 0)
- perror_with_name (name);
- val = myread (desc, stringtab, stsize);
- if (val < 0)
- perror_with_name (name);
-#endif /* 0 */
- stringtab = symfile_string_table;
- stsize = symfile_string_table_size;
-
- 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");
- }
-
- /* Search through list for correct name. */
- for (result = symtab_list; result; result = result->next)
- if (!strcmp (result->filename, pst->filename))
- return result;
-
- return 0;
-}
-
-/*
- * 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 (prev) = SYMBOL_VALUE (sym);
- else
- global_sym_chain[hash]
- = (struct symbol *) SYMBOL_VALUE (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 (sym) = misc_function_vector[mf].address;
-
- if (prev)
- sym = (struct symbol *) SYMBOL_VALUE (prev);
- else
- sym = global_sym_chain[hash];
- }
- else
- {
- prev = sym;
- sym = (struct symbol *) SYMBOL_VALUE (sym);
- }
- }
- }
-}
-
-/*
- * 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 offset to be added to
- * all values of symbols coming in and
- * TEXT_SIZE is the size of the text segment read in.
- * OFFSET is a flag which indicates that the value of all of the
- * symbols should be offset by TEXT_OFFSET (for the purposes of
- * incremental linking).
- */
-
-static void
-read_ofile_symtab (desc, stringtab, stringtab_size, sym_offset,
- sym_size, text_offset, text_size, offset)
- int desc;
- register char *stringtab;
- int sym_offset;
- int sym_size;
- int text_offset;
- int text_size;
- int offset;
-{
- register char *namestring;
- register struct symbol *sym, *prev;
- int hash;
- struct cleanup *old_chain;
- struct nlist *bufp;
- unsigned char type;
-#ifdef N_BINCL
- subfile_stack = 0;
-#endif
-
- 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 >= sizeof (struct nlist))
- {
- lseek (desc, sym_offset - sizeof (struct nlist), L_INCR);
- fill_symbuf ();
- bufp = &symbuf[symbuf_idx++];
-
- 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 ((unsigned char) bufp->n_type != N_SO)
- fatal("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++];
- type = bufp->n_type;
-
- if (offset &&
- (type == N_TEXT || type == N_DATA || type == N_BSS))
- bufp->n_value += text_offset;
-
- 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)
- process_one_symbol(type, bufp->n_desc,
- bufp->n_value, 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 == N_TEXT
-#ifdef N_NBTEXT
- || type == N_NBTEXT
-#endif
- )
- /* 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. */
- &stringtab_global; /* For debugger; am I right? */
- }
- end_symtab (text_offset + text_size);
-}
-
-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;
-}
-
-/* Put all appropriate global symbols in the symseg data
- onto the hash chains so that their addresses will be stored
- when seen later in loader global symbols. */
-
-static void
-hash_symsegs ()
-{
- /* Look at each symbol in each block in each symseg symtab. */
- struct symtab *s;
- for (s = symseg_chain; s; s = s->next)
- {
- register int n;
- for (n = BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)) - 1; n >= 0; n--)
- {
- register struct block *b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), n);
- register int i;
- for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--)
- {
- register struct symbol *sym = BLOCK_SYM (b, i);
-
- /* Put the symbol on a chain if its value is an address
- that is figured out by the loader. */
-
- if (SYMBOL_CLASS (sym) == LOC_EXTERNAL)
- {
- register int hash = hashname (SYMBOL_NAME (sym));
- SYMBOL_VALUE (sym) = (int) global_sym_chain[hash];
- global_sym_chain[hash] = sym;
- SYMBOL_CLASS (sym) = LOC_STATIC;
- }
- }
- }
- }
-}
-
-static void
-process_one_symbol (type, desc, value, name)
- int type, desc;
- CORE_ADDR value;
- char *name;
-{
- 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 != N_SO)
- {
- /* Currently this ignores N_ENTRY on Gould machines, N_NSYM on machines
- where that code is defined. */
- if (IGNORE_SYMBOL (type))
- return;
-
- 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. */
-
- colon_pos = index (name, ':');
- if (!colon_pos++
- || (*colon_pos != 'f' && *colon_pos != 'F'))
- {
- define_symbol (value, name, desc);
- 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, value);
- }
- /* 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 = value;
- new->name = define_symbol (value, name, desc);
- local_symbols = 0;
- break;
-
- case N_LBRAC:
- /* This "symbol" just indicates the start of an inner lexical
- context within a function. */
-
- 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 = value;
- 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. */
- 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 native 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. */
-#if !defined (VARIABLES_INSIDE_BLOCK)
-#define VARIABLES_INSIDE_BLOCK(desc) 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))
- 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))
- {
- /* Muzzle a compiler bug that makes end < start. */
- if (new->start_addr > value)
- new->start_addr = value;
- /* Make a block for the local symbols within. */
- finish_block (0, &local_symbols, new->old_blocks,
- new->start_addr + last_source_start_addr,
- value + last_source_start_addr);
- }
- else
- {
- within_function = 0;
- }
- if (VARIABLES_INSIDE_BLOCK(desc))
- /* 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. */
-#ifdef PCC_SOL_BROKEN
- /* pcc bug, occasionally puts out SO for SOL. */
- if (context_stack_depth > 0)
- {
- start_subfile (name);
- break;
- }
-#endif
- if (last_source_file)
- end_symtab (value);
- start_symtab (name, value);
- 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);
- break;
-
-#ifdef N_BINCL
- case N_BINCL:
- push_subfile ();
- add_new_header_file (name, value);
- start_subfile (name);
- break;
-
- case N_EINCL:
- start_subfile (pop_subfile ());
- break;
-
- case N_EXCL:
- add_old_header_file (name, value);
- break;
-#endif /* have N_BINCL */
-
- 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. */
- record_line (desc, value);
- 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 pending *link = local_symbols;
- 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 (sym) = (int) 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 (value, name, desc);
- }
-}
-
-/* This function was added for C++ functionality. I presume that it
- condenses the bunches formed by reading in an additional .o file
- (incremental linking). */
-
-static void
-condense_addl_misc_bunches ()
-{
- register int i, j;
- register struct misc_bunch *bunch;
-#ifdef NAMES_HAVE_UNDERSCORE
- int offset = 1;
-#else
- int offset = 0;
-#endif
-
- misc_function_vector
- = (struct misc_function *) xrealloc (misc_function_vector,
- (misc_count + misc_function_count) * sizeof (struct misc_function));
-
- j = misc_function_count;
- bunch = misc_bunch;
- while (bunch)
- {
- for (i = 0; i < misc_bunch_index; i++)
- {
- misc_function_vector[j] = bunch->contents[i];
- misc_function_vector[j].name
- = concat (misc_function_vector[j].name
- + (misc_function_vector[j].name[0] == '_' ? offset : 0),
- "", "");
- j++;
- }
- bunch = bunch->next;
- misc_bunch_index = MISC_BUNCH_SIZE;
- }
-
- misc_function_count += misc_count;
-
- /* Sort the misc functions by address. */
-
- qsort (misc_function_vector, misc_function_count,
- sizeof (struct misc_function), compare_misc_functions);
-}
-
-
-/* Read in another .o file and create a symtab entry for it.*/
-
-static void
-read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size)
- int desc;
- register char *stringtab;
- register int nlistlen;
- unsigned text_addr;
- int text_size;
-{
- FILE *stream = fdopen (desc, "r");
- register char *namestring;
- register struct symbol *sym, *prev;
- int hash;
-
-#ifdef N_BINCL
- subfile_stack = 0;
-#endif
-
- last_source_file = 0;
- bzero (global_sym_chain, sizeof global_sym_chain);
- symtab_input_desc = desc;
- stringtab_global = stringtab;
- fill_symbuf ();
-
- for (symnum = 0; symnum < nlistlen; symnum++)
- {
- struct nlist *bufp;
- unsigned char type;
-
- QUIT; /* allow this to be interruptable */
- if (symbuf_idx == symbuf_end)
- fill_symbuf ();
- bufp = &symbuf[symbuf_idx++];
- type = bufp->n_type & N_TYPE;
- namestring = bufp->n_un.n_strx + stringtab;
-
- if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) )
- {
- /* Relocate this file's symbol table information
- to the address it has been loaded into. */
- bufp->n_value += text_addr;
- }
-
- type = bufp->n_type;
-
- if (type & N_STAB)
- process_one_symbol (type, bufp->n_desc,
- bufp->n_value, namestring);
- /* A static text symbol whose name ends in ".o"
- can only mean the start of another object file.
- So end the symtab of the source file we have been processing.
- This is how we avoid counting the libraries as part
- or the last source file.
- Also this way we find end of first object file (crt0). */
- else if ((type == N_TEXT
-#ifdef N_NBTEXT
- || type == N_NBTEXT
-#endif
- )
- && (!strcmp (namestring + strlen (namestring) - 2, ".o"))
- || ! strncmp (namestring, "-l", 2))
- {
- if (last_source_file)
- end_symtab (bufp->n_value);
- }
- else if (type & N_EXT || type == N_TEXT
-#ifdef N_NBTEXT
- || type == N_NBTEXT
-#endif
- )
- {
- int used_up = 0;
-
- /* Record the location of _etext. */
- if (type == (N_TEXT | N_EXT)
- && !strcmp (namestring, "_etext"))
- end_of_text_addr = bufp->n_value;
-
-#if 0
- /* 25 Sep 89: The following seems to be stolen from
- read_ofile_symtab, and is wrong here (i.e. there was no
- first pass for add-file symbols). */
- /* This shouldn't be necessary, as we now do all of this work
- in scan_global syms and all misc functions should have been
- recorded on the first pass. */
- /* Global symbol: see if we came across a dbx definition
- 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. */
- if (type & N_EXT)
- {
- prev = 0;
-#ifdef NAMES_HAVE_UNDERSCORE
- hash = hashname (namestring + 1);
-#else /* not NAMES_HAVE_UNDERSCORE */
- hash = hashname (namestring);
-#endif /* not NAMES_HAVE_UNDERSCORE */
- for (sym = global_sym_chain[hash];
- sym;)
- {
- if (
-#ifdef NAMES_HAVE_UNDERSCORE
- *namestring == '_'
- && namestring[1] == SYMBOL_NAME (sym)[0]
- &&
- !strcmp (namestring + 2, SYMBOL_NAME (sym) + 1)
-#else /* NAMES_HAVE_UNDERSCORE */
- namestring[0] == SYMBOL_NAME (sym)[0]
- &&
- !strcmp (namestring + 1, SYMBOL_NAME (sym) + 1)
-#endif /* NAMES_HAVE_UNDERSCORE */
- )
- {
- if (prev)
- SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym);
- else
- global_sym_chain[hash]
- = (struct symbol *) SYMBOL_VALUE (sym);
- if (SYMBOL_CLASS (sym) == LOC_BLOCK)
- fix_common_block (sym, bufp->n_value);
- else
- SYMBOL_VALUE (sym) = bufp->n_value;
- if (prev)
- sym = (struct symbol *) SYMBOL_VALUE (prev);
- else
- sym = global_sym_chain[hash];
-
- used_up = 1;
- }
- else
- {
- prev = sym;
- sym = (struct symbol *) SYMBOL_VALUE (sym);
- }
- }
- }
-
- /* Defined global or text symbol: record as a misc function
- if it didn't give its address to a debugger symbol above. */
- if (type <= (N_TYPE | N_EXT)
- && type != N_EXT
- && ! used_up)
- record_misc_function (namestring, bufp->n_value,
- bufp->n_type);
-#endif /* 0 */
- }
- }
-
- if (last_source_file)
- end_symtab (text_addr + text_size);
-
- fclose (stream);
-}
-
-/* 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. */
-
-void
-add_file_command (arg_string)
- char* arg_string;
-{
- register int desc;
- DECLARE_FILE_HEADERS;
- struct nlist *nlist;
- char *stringtab;
- long buffer;
- register int val;
- extern void close ();
- struct cleanup *old_chain;
- struct symtab *symseg;
- struct stat statbuf;
- char *name;
- unsigned text_addr;
-
- 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.");
-
- desc = open (name, O_RDONLY);
- if (desc < 0)
- perror_with_name (name);
-
- old_chain = make_cleanup (close, desc);
-
- READ_FILE_HEADERS (desc, name);
-
- if (NUMBER_OF_SYMBOLS == 0)
- {
- printf ("%s does not have a symbol-table.\n", name);
- fflush (stdout);
- return;
- }
-
- printf ("Reading symbol data from %s...", name);
- fflush (stdout);
-
- /* Now read the string table, all at once. */
- val = lseek (desc, STRING_TABLE_OFFSET, 0);
- if (val < 0)
- perror_with_name (name);
- if (stat (name, &statbuf) < 0)
- perror_with_name (name);
- READ_STRING_TABLE_SIZE (buffer);
- if (buffer >= 0 && buffer < statbuf.st_size)
- {
-#ifdef BROKEN_LARGE_ALLOCA
- stringtab = (char *) xmalloc (buffer);
- make_cleanup (free, stringtab);
-#else
- stringtab = (char *) alloca (buffer);
-#endif
- }
- else
- stringtab = NULL;
- if (stringtab == NULL)
- error ("ridiculous string table size: %d bytes", buffer);
-
- /* Usually READ_STRING_TABLE_SIZE will have shifted the file pointer.
- Occaisionally, it won't. */
- val = lseek (desc, STRING_TABLE_OFFSET, 0);
- if (val < 0)
- perror_with_name (name);
- val = myread (desc, stringtab, buffer);
- if (val < 0)
- perror_with_name (name);
-
- /* Symsegs are no longer supported by GDB. Setting symseg_chain to
- 0 is easier than finding all the symseg code and eliminating it. */
- symseg_chain = 0;
-
- /* Position to read the symbol table. Do not read it all at once. */
- val = lseek (desc, SYMBOL_TABLE_OFFSET, 0);
- if (val < 0)
- perror_with_name (name);
-
- init_misc_functions ();
- make_cleanup (discard_misc_bunches, 0);
- init_header_files ();
- make_cleanup (free_header_files, 0);
- free_pendings = 0;
- pending_blocks = 0;
- file_symbols = 0;
- global_symbols = 0;
- make_cleanup (really_free_pendings, 0);
-
- read_addl_syms (desc, stringtab, NUMBER_OF_SYMBOLS, text_addr,
- SIZE_OF_TEXT_SEGMENT);
-
-
- /* Sort symbols alphabetically within each block. */
-
- sort_syms ();
-
- /* Go over the misc functions and install them in vector. */
-
- condense_addl_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);
-
- /* Free the symtabs made by read_symsegs, but not their contents,
- which have been copied into symtabs on symtab_list. */
- while (symseg_chain)
- {
- register struct symtab *s = symseg_chain->next;
- free (symseg_chain);
- symseg_chain = s;
- }
-
- printf ("done.\n");
- fflush (stdout);
-}
-
-/* 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);
- }
-}
-
-
-
-static struct symbol *
-define_symbol (value, string, desc)
- int value;
- char *string;
- int desc;
-{
- register struct symbol *sym
- = (struct symbol *) obstack_alloc (symbol_obstack, sizeof (struct symbol));
- char *p = (char *) index (string, ':');
- int deftype;
- 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;
-
- 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. */
- if ((*p >= '0' && *p <= '9') || *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 *value;
-
- SYMBOL_TYPE (sym) = builtin_type_double;
- value = (char *) obstack_alloc (symbol_obstack, sizeof (double));
- bcopy (&d, value, sizeof (double));
- SYMBOL_VALUE_BYTES (sym) = value;
- 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 = 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 '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 (sym) = (int) 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) = value;
- SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
- add_symbol_to_list (sym, &local_symbols);
- break;
-
- case 'p':
- SYMBOL_CLASS (sym) = LOC_ARG;
- SYMBOL_VALUE (sym) = value;
- 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 (value);
- SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
- add_symbol_to_list (sym, &local_symbols);
- break;
-
- case 'r':
-/* XXX */
-#ifdef sparc
-{
- struct symbol *s0;
-
- /*
- * If we see a parm decl immediately followed by a reg decl of
- * the same name (and in the same block), we change it to a single
- * instance of a reg parm. Sun's cc will generate these.
- */
- if (local_symbols &&
- (s0 = local_symbols->symbol[local_symbols->nsyms - 1]) &&
- SYMBOL_CLASS(s0) == LOC_ARG &&
- strcmp(SYMBOL_NAME(s0), SYMBOL_NAME(sym)) == 0) {
- SYMBOL_CLASS (s0) = LOC_REGPARM;
- SYMBOL_VALUE (s0) = STAB_REG_TO_REGNUM (value);
- SYMBOL_NAMESPACE (s0) = VAR_NAMESPACE;
- return s0;
- }
-}
-#endif
- SYMBOL_CLASS (sym) = LOC_REGISTER;
- SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (value);
- 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 (sym) = value;
- SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
- add_symbol_to_list (sym, &file_symbols);
- break;
-
- case 't':
- SYMBOL_CLASS (sym) = LOC_TYPEDEF;
- SYMBOL_VALUE (sym) = value;
- 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)); i > 0; i--)
- if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) == 0)
- TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i - 1) =
- TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i));
- }
-
- add_symbol_to_list (sym, &file_symbols);
- break;
-
- case 'T':
- SYMBOL_CLASS (sym) = LOC_TYPEDEF;
- SYMBOL_VALUE (sym) = value;
- 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);
- break;
-
- case 'V':
- /* Static symbol of local scope */
- SYMBOL_CLASS (sym) = LOC_STATIC;
- SYMBOL_VALUE (sym) = value;
- 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) = value;
- 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) = value;
- 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;
-}
-
-/* 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, *ntype;
- struct symbol *sym;
-
- for (type = undef_types; type < undef_types + undef_types_length; type++)
- {
- struct type *ntype = 0;
- /* 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;
-}
-
-
-
-/* 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;
- register int n;
- struct type *type1;
- int typenums[2];
- int xtypenums[2];
- char *tmpc;
-
- /* 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:
- error ("Bad type cross reference at symnum: %d.", symnum);
- }
-
- to = type_name = (char *)
- obstack_alloc (symbol_obstack,
- (strlen (prefix) +
- ((char *) index (*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 *) index (*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);
- if (TYPE_POINTER_TYPE (type1))
- {
- type = TYPE_POINTER_TYPE (type1);
- if (typenums[0] != -1)
- *dbx_lookup_type (typenums) = type;
- }
- else
- {
- type = dbx_alloc_type (typenums);
- smash_to_pointer_type (type, type1);
- }
- break;
-
- case '@':
- {
- struct type *domain = read_type (pp);
- char c;
- struct type *memtype;
-
- if (*(*pp)++ != ',')
- error ("invalid member type data format, at symtab pos %d.",
- symnum);
-
- memtype = read_type (pp);
- type = dbx_alloc_type (typenums);
- smash_to_member_type (type, domain, memtype);
- }
- break;
-
- case '#':
- {
- struct type *domain = read_type (pp);
- char c;
- 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);
- if (TYPE_REFERENCE_TYPE (type1))
- {
- type = TYPE_REFERENCE_TYPE (type1);
- if (typenums[0] != -1)
- *dbx_lookup_type (typenums) = type;
- }
- else
- {
- type = dbx_alloc_type (typenums);
- smash_to_reference_type (type, type1);
- }
- break;
-
- case 'f':
- type1 = read_type (pp);
- if (TYPE_FUNCTION_TYPE (type1))
- {
- type = TYPE_FUNCTION_TYPE (type1);
- if (typenums[0] != -1)
- *dbx_lookup_type (typenums) = type;
- }
- else
- {
- type = dbx_alloc_type (typenums);
- smash_to_function_type (type, type1);
- }
- 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 = read_struct_type (pp, type);
- break;
-
- case 'u':
- type = dbx_alloc_type (typenums);
- type = read_struct_type (pp, type);
- TYPE_CODE (type) = TYPE_CODE_UNION;
- break;
-
- case 'a':
- if (*(*pp)++ != 'r')
- error ("Invalid symbol data: unrecognized type-code `a%c' %s %d.",
- (*pp)[-1], "at symtab position", symnum);
-
- type = dbx_alloc_type (typenums);
- type = read_array_type (pp, type);
- break;
-
- default:
- error ("Invalid symbol data: unrecognized type-code `%c' at symtab pos %d.",
- (*pp)[-1], symnum);
- }
-
- 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;
-}
-
-/* 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 (pp, type)
- char **pp;
- register struct type *type;
-{
- struct nextfield
- {
- struct nextfield *next;
- int visibility;
- struct field field;
- };
-
- struct next_fnfield
- {
- struct next_fnfield *next;
- int visibility;
- 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;
- int totalsize;
- char *name;
- register char *p;
- int nfields = 0;
- register int n;
-
- register struct next_fnfieldlist *mainlist = 0;
- int nfn_fields = 0;
- int read_possible_virtual_info = 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_vec;
- 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, ',');
- baseclass_vec = (struct type **)
- obstack_alloc (symbol_obstack,
- (n_baseclasses) * sizeof (struct type **)) - 1;
-
- for (i = 1; 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:
- error ("Invalid symbol data: bad visibility format at symtab pos %d",
- symnum);
- }
-
- switch (*(*pp)++)
- {
- case '0':
- via_public = 0;
- break;
- case '2':
- via_public = 1;
- break;
- default:
- error ("Invalid symbol data: bad visibility format at symtab pos %d.",
- symnum);
- }
-
- /* 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 (offset != 0)
- {
- static int error_printed = 0;
-
- if (!error_printed)
- {
- fprintf (stderr,
-"\nWarning: GDB has limited understanding of multiple inheritance...");
- error_printed = 1;
- }
- offset = 0;
- }
-
- baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public);
-
- /* Since lookup_basetype_type can copy the type,
- it might copy a stub type (complete with stub flag).
- If so, we need to add it to the list of undefined types
- to clean up later. Even if lookup_basetype_type
- didn't copy the type, adding it to the undefined list
- will not do any harm. */
- if (TYPE_FLAGS(baseclass_vec[i]) & TYPE_FLAG_STUB)
- add_undefined_type (baseclass_vec[i]);
-
- /* Make this baseclass visible for structure-printing purposes. */
- new = (struct nextfield *) alloca (sizeof (struct nextfield));
- new->next = list;
- list = new;
- list->field.type = baseclass_vec[i];
- list->field.name = TYPE_NAME (baseclass_vec[i]);
- list->field.bitpos = offset;
- list->field.bitsize = 0; /* this should be an unpacked field! */
- nfields++;
- }
- TYPE_N_BASECLASSES (type) = n_baseclasses;
- TYPE_BASECLASSES (type) = baseclass_vec;
- }
-
- /* 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 '+' (public visibility),
- '0' (protected visibility), and '-' (private visibility). */
-
- /* We better set p right now, in case there are no fields at all... */
- p = *pp;
-
- while (**pp != ';')
- {
- int visibility;
-
- /* 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;
- 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':
- visibility = 0;
- *pp += 1;
- break;
-
- case '1':
- visibility = 1;
- *pp += 1;
- break;
-
- case '2':
- visibility = 2;
- *pp += 1;
- break;
- }
- }
- /* else normal dbx-style format. */
-
- list->field.type = read_type (pp);
- if (**pp == ':')
- {
- 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 != ',')
- error ("Invalid symbol data: bad structure-type format at symtab pos %d.",
- symnum);
- (*pp)++; /* Skip the comma. */
- list->field.bitpos = read_number (pp, ',');
- list->field.bitsize = read_number (pp, ';');
-
-#if 0
- /* 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)
- {
- /* Have we given the warning yet? */
- static int warning_given = 0;
-
- /* Only give the warning once, no matter how many class
- variables there are. */
- if (!warning_given)
- {
- warning_given = 1;
- fprintf_filtered (stderr, "\n\
-Warning: DBX-style class variable debugging information encountered.\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.\n\
-");
- }
-
- /* 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++;
- }
- }
-
- /* 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. */
-
- p = *pp;
-
- /* chill the list of fields: the last entry (at the head)
- is a partially constructed entry which we now scrub. */
- list = list->next;
-
- /* For each list of method lists... */
- do
- {
- int i;
- struct next_fnfield *sublist = 0;
- struct fn_field *fn_fields = 0;
- int length = 0;
- struct next_fnfieldlist *new_mainlist =
- (struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist));
-
- /* read in the name. */
- while (*p != ':') p++;
- if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == '$')
- {
- static char opname[] = "operator";
- char *o = opname + strlen(opname);
-
- /* Skip past '::'. */
- p += 2;
- while (*p != '.')
- *o++ = *p++;
- new_mainlist->fn_fieldlist.name = savestring (opname, o - opname);
- /* Skip past '.' */
- *pp = p + 1;
- }
- else
- {
- i = 0;
- new_mainlist->fn_fieldlist.name = savestring (*pp, p - *pp);
- /* Skip past '::'. */
- *pp = p + 2;
- }
-
- 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 != ':')
- error ("invalid symtab info for method at symbol number %d.",
- symnum);
- *pp += 1;
- new_sublist->fn_field.args =
- TYPE_ARG_TYPES (new_sublist->fn_field.type);
- p = *pp;
- while (*p != ';') p++;
- new_sublist->fn_field.physname = savestring (*pp, p - *pp);
- *pp = p + 1;
- new_sublist->visibility = *(*pp)++ - '0';
- if (**pp == '\\') *pp = next_symbol_text ();
-
- switch (*(*pp)++)
- {
- case '*':
- /* virtual member function, followed by index. */
- new_sublist->fn_field.voffset = read_number (pp, ';') + 1;
- break;
- case '?':
- /* static member function. */
- new_sublist->fn_field.voffset = 1;
- break;
- default:
- /* **pp == '.'. */
- /* normal member function. */
- new_sublist->fn_field.voffset = 0;
- break;
- }
-
- new_sublist->next = sublist;
- sublist = new_sublist;
- length++;
- }
- while (**pp != ';');
-
- *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) =
- (int *) obstack_alloc (symbol_obstack,
- sizeof (int) * (1 + (length >> 5)));
-
- TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) =
- (int *) obstack_alloc (symbol_obstack,
- sizeof (int) * (1 + (length >> 5)));
-
- for (i = length; 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++;
- }
- while (**pp != ';');
- }
-
- *pp += 1;
-
- /* 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);
- TYPE_FIELD_PRIVATE_BITS (type) =
- (int *) obstack_alloc (symbol_obstack,
- sizeof (int) * (1 + (nfields >> 5)));
- TYPE_FIELD_PROTECTED_BITS (type) =
- (int *) obstack_alloc (symbol_obstack,
- sizeof (int) * (1 + (nfields >> 5)));
-
- TYPE_NFN_FIELDS (type) = nfn_fields;
- TYPE_NFN_FIELDS_TOTAL (type) = nfn_fields;
-
- {
- int i;
- for (i = 1; i <= TYPE_N_BASECLASSES (type); ++i)
- TYPE_NFN_FIELDS_TOTAL (type) +=
- TYPE_NFN_FIELDS_TOTAL (TYPE_BASECLASS (type, i));
- }
-
- TYPE_FN_FIELDLISTS (type) =
- (struct fn_fieldlist *) obstack_alloc (symbol_obstack,
- sizeof (struct fn_fieldlist) * nfn_fields);
-
- /* Copy the saved-up fields into the field vector. */
-
- for (n = nfields; list; list = list->next)
- {
- 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);
- }
-
- 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 != ';') p++;
- TYPE_VPTR_BASETYPE (type) = t;
- if (type == t)
- {
- if (TYPE_FIELD_NAME (t, 0) == 0)
- TYPE_VPTR_FIELDNO (type) = i = 0;
- else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i)
- if (! strncmp (TYPE_FIELD_NAME (t, i), *pp,
- strlen (TYPE_FIELD_NAME (t, i))))
- {
- TYPE_VPTR_FIELDNO (type) = i;
- break;
- }
- if (i < 0)
- error ("virtual function table field not found");
- }
- else
- TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, 1));
- *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)++ != ';')
- error ("Invalid symbol data; improper format of array type decl.");
-
- 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++)
- {
- 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;
-}
-
-#define MAX_OF_TYPE(t) ((1 << (sizeof (t) - 1)) - 1)
-#define MIN_OF_TYPE(t) (-(1 << (sizeof (t) - 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;
- struct type *index_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)
- error ("Unrecognized type range %s.", pp);
-
- if (n2bits != 0 || n3bits != 0)
-#ifdef LONG_LONG
- {
- 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 fro <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;
- }
-
- /* Check for "long long". */
- if (got_signed && nbits == CHAR_BIT * sizeof (long long))
- return builtin_type_long_long;
- if (got_unsigned && nbits == CHAR_BIT * sizeof (long long))
- return builtin_type_unsigned_long_long;
-
- error ("Large type isn't a long long.");
- }
-#else /* LONG_LONG */
- error ("Type long long not supported on this machine.");
-#endif
-
- /* 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 */
- if (n3 == UINT_MAX)
- return builtin_type_unsigned_int;
- if (n3 == ULONG_MAX)
- return builtin_type_unsigned_long;
- if (n3 == USHRT_MAX)
- return builtin_type_unsigned_short;
- if (n3 == UCHAR_MAX)
- 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 == INT_MAX)
- return builtin_type_int;
- if (n3 == LONG_MAX)
- return builtin_type_long;
- if (n3 == SHRT_MAX)
- return builtin_type_short;
- if (n3 == CHAR_MAX)
- 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)
- error ("Type defined as subrange of itself: %s.", 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
- error ("Ranged type doesn't fit within known sizes.");
-
- 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;
-}
-
-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;
- long upper_limit;
-
- /* Handle an optional leading minus sign. */
-
- 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++;
- }
-
- upper_limit = LONG_MAX / radix;
- while ((c = *p++) >= '0' && c <= '9')
- {
- if (n <= upper_limit)
- {
- n *= radix;
- n += c - '0';
- }
- 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;
- }
-}
-
-/* Read in an argument list. This is a list of types. It is terminated with
- a ':', FYI. Return the list of types read in. */
-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 != ',')
- error ("Invalid argument list: no ',', at symtab pos %d", symnum);
- *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;
-}
-
-/* This function is really horrible, but to avoid it, there would need
- to be more filling in of forward references. THIS SHOULD BE MOVED OUT
- OF COFFREAD.C AND DBXREAD.C TO SOME PLACE WHERE IT CAN BE SHARED */
-int
-fill_in_vptr_fieldno (type)
- struct 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);
-}
-
-/* Copy a pending list, used to record the contents of a common
- block for later fixup. BUG FIX by rde@topexpress.co.uk */
-static struct pending *
-copy_pending (beg, begi, end)
- struct pending *beg, *end;
- int begi;
-{
- struct pending *new = 0;
- struct pending *next;
-
- /* rde note: `begi' is an offset in block `end', NOT `beg' */
- for (next = beg; next != 0; next = next->next)
- {
- register int j;
- for (j = next == end ? begi : 0; j < next->nsyms; j++)
- add_symbol_to_list (next->symbol[j], &new);
-
- if (next == end)
- break;
- }
- 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, value)
- struct symbol *sym;
- int value;
-{
- 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 (next->symbol[j]) += value;
- }
-}
-
-void
-_initialize_dbxread ()
-{
- symfile = 0;
- header_files = (struct header_file *) 0;
- this_object_header_files = (int *) 0;
-
- undef_types_allocated = 20;
- undef_types_length = 0;
- undef_types = (struct type **) xmalloc (undef_types_allocated *
- sizeof (struct type *));
-
- add_com ("symbol-file", class_files, symbol_file_command,
- "Load symbol table (in dbx format) from executable file FILE.");
-
- add_com ("add-file", class_files, add_file_command,
- "Load the symbols from FILE, assuming its code is at TEXT_START.") ;
-}
-
-#endif /* READ_DBX_FORMAT */
diff --git a/gnu/usr.bin/gdb/defs.h b/gnu/usr.bin/gdb/defs.h
deleted file mode 100644
index de744fce78a6..000000000000
--- a/gnu/usr.bin/gdb/defs.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * @(#)defs.h 6.3 (Berkeley) 5/8/91
- */
-
-/* Basic 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. */
-
-#define CORE_ADDR unsigned int
-
-#define min(a, b) ((a) < (b) ? (a) : (b))
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
-extern char *savestring ();
-extern char *concat ();
-extern char *xmalloc (), *xrealloc ();
-extern int parse_escape ();
-extern char *reg_names[];
-
-/* Various possibilities for alloca. */
-#ifdef sparc
-#include <alloca.h>
-#else
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else
-extern char *alloca ();
-#endif
-#endif
-
-extern int quit_flag;
-
-extern int immediate_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
-{
- 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;
-};
-
-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 void reinitialize_more_filter ();
-extern void fputs_filtered ();
-extern void fprintf_filtered ();
-extern void printf_filtered ();
-extern void print_spaces_filtered ();
-extern char *tilde_expand ();
-
-/* Structure for saved commands lines
- (for breakpoints, defined commands, etc). */
-
-struct command_line
-{
- struct command_line *next;
- char *line;
- int type; /* statement type */
-#define CL_END 0
-#define CL_NORMAL 1
-#define CL_WHILE 2
-#define CL_IF 3
-#define CL_EXITLOOP 4
-#define CL_NOP 5
- struct command_line *body; /* body of loop for while, body of if */
- struct command_line *elsebody; /* body of else part of if */
-};
-
-extern struct command_line *read_command_lines ();
-extern void do_command_lines();
-
-/* String containing the current directory (what getwd would return). */
-
-char *current_directory;
-
diff --git a/gnu/usr.bin/gdb/doc/ChangeLog b/gnu/usr.bin/gdb/doc/ChangeLog
new file mode 100644
index 000000000000..fb867193a4aa
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/ChangeLog
@@ -0,0 +1,783 @@
+Tue Oct 19 14:21:18 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo (Sourc Path): index entries for $cwd, $pdir
+
+ * a4rc.sed: update to work with Andreas Vogel papersize params
+
+ * refcard.tex: use Andreas Vogel simplifications of papersize
+ params; remove useless version info; update copyright date.
+
+Tue Oct 19 10:46:22 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Symbols): Add class NAME to doc for ptype.
+
+Tue Oct 12 09:11:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Files): Say what address the load command loads it at.
+
+ * stabs.texinfo (Common Blocks): Minor cleanups.
+
+ * stabs.texinfo: Update ld stabs in elf relocation to reflect the fact
+ that Sun has backed away from the linker kludge and thus the relevant
+ issue is changes to the SunPRO tools, not the Solaris linker.
+
+ * stabs.texinfo (Traditional Integer Types): Clean up description
+ of octal bounds a little bit. Document extra leading zeroes.
+
+Thu Oct 7 16:15:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Signaling): Update for symbolic symbol names
+ and add a section explaining the difference between the GDB
+ signal command and the shell kill utility.
+
+Wed Oct 6 13:23:01 1993 Tom Lord (lord@rtl.cygnus.com)
+
+ * libgdb.texinfo: added `@' to braces that were unescaped.
+
+Mon Oct 4 10:42:18 1993 Tom Lord (lord@rtl.cygnus.com)
+
+ * libgdb.texinfo: new file. Spec for the gdb library.
+
+Sun Oct 3 15:26:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Include Files): Fix typo (start -> end).
+
+Thu Sep 30 18:24:56 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, remote.texi: assorted small improvements, mostly
+ from Melissa at FSF's editing pass.
+
+Thu Sep 30 11:54:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo: Remove stuff about ar and 14 character filenames.
+ I believe this was fixed by the 13 Sep 89 change to print_frame_info.
+ Also, modern versions of ar like BSD 4.4 or SVR4 don't have this bug.
+
+Wed Sep 22 21:22:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.texi (Bootstrapping): Discuss 386 call gates.
+
+Sat Sep 18 17:10:44 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * stabs.texinfo (Based Variables): New node.
+
+Thu Sep 16 17:48:55 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Re-write discussions of
+ names, sizes, and formats to suggest how not to lose.
+
+Sat Sep 11 09:35:11 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * stabs.texinfo (Methods): Fix typo.
+
+Fri Sep 10 06:34:20 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * gdb.texinfo: Fix a few typos.
+
+Wed Sep 8 09:11:52 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo: Clarify how well it works with Fortran.
+
+ * stabs.texinfo (Stabs In ELF, Statics, ELF Transformations):
+ More on relocating stabs in ELF files.
+
+Tue Sep 7 13:45:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stabs In ELF): Talk about N_FUN value.
+
+Mon Sep 6 19:23:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Local Variable Parameters): Talk about nameless
+ parameters on VAX.
+
+Fri Sep 3 17:06:08 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: @up/@down -> @raisesections/@lowersections
+
+Fri Sep 3 12:04:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Make info author notice match the TeX author notice.
+
+Tue Aug 31 13:21:06 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * stabs.texinfo: Initial-caps all words in node names and
+ non-trivial words in section names.
+
+Mon Aug 30 11:13:16 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Many minor cleanups.
+
+ * stabs.texinfo: Remove @deffn except from Expanded Reference node.
+
+Sat Aug 28 12:08:09 1993 David J. MacKenzie (djm@edison.eng.umd.edu)
+
+ * stabs.texinfo: Remove full description of big example.
+ It's not really helpful; just use pieces of it where appropriate.
+ Add more Texinfo formatting directives (@samp, etc.).
+ Use @deffn to define stab types.
+ Eliminate some wordiness. Break up some nodes.
+ Add an (alphabetized) index of symbol types.
+ Use consistent capitalization style in node and section names.
+
+Thu Aug 26 06:36:31 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * gdb.texinfo: Change typo "Two two" to "The two".
+
+Sun Aug 22 12:15:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (XCOFF-differences): Remove references to
+ non-existent types N_DECL and N_RPSYM.
+
+ * stabs.texinfo (String Field): Say that type attributes bug is
+ fixed in GDB 4.10, since it is.
+
+ * stabs.texinfo: Clean up djm cleanups, and more cleanups of my own.
+
+Sat Aug 21 04:32:28 1993 David MacKenzie (djm@cygnus.com)
+
+ * stabs.texinfo: Formatting cleanups.
+
+Fri Aug 20 20:49:53 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: When explaining the n_type of a stab, standardize
+ how we do it ('#' as a comment indicator, "36 is N_FUN" as text,
+ no tabs, use @r).
+ (Global Variables): Clean up.
+
+Tue Aug 17 15:57:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stack Variables): Re-write.
+
+Mon Aug 16 21:20:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stabs-in-elf): Talk about getting the start
+ addresses of a source file. Also revise formatting.
+ Change "object module" or "object file" to "source file".
+ Various: Miscellaneous cleanups.
+
+Thu Aug 12 15:11:51 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Point to mangling info in gcc's gpcompare.texi.
+
+Tue Aug 10 16:57:49 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * gdbint.texinfo: Removed many nonsensical machine-collected
+ host and target conditionals, described some of the remainder.
+
+Tue Aug 10 13:28:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbint.texinfo (Getting Started): Use @itemize, not @table.
+
+ * gdbint.texinfo (Top): Add name to @top line, and re-write the
+ paragraph which follows.
+
+ * gdbint.texinfo (Host): Use @code not @samp for Makefile
+ variables. Looks better and avoids overful hbox.
+
+Fri Jul 30 18:26:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Procedures): Improve stuff on nested functions.
+
+Thu Jul 29 15:10:58 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * remote.texi: (MIPS Remote) clearer doc for set/show timeout,
+ retransmit-timeout
+
+Thu Jul 29 13:16:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbint.texinfo: Update statement about `some ancient Unix
+ systems, like Ultrix 4.0' to Ultrix 4.2.
+
+Wed Jul 28 15:26:53 1993 Roland H. Pesch (pesch@el_bosque.cygnus.com)
+
+ * h8-cfg.texi, all-cfg.texi: new flag GDBSERVER
+
+ * Makefile.in: depend on remote.texi rather than gdbinv-s.texi
+
+ * remote.texi: (Server) New node on gdbserver. (Remote Serial,
+ ST2000 Remote, MIPS Remote): mention `host:port' syntax for TCP.
+
+ * remote.texi: new name for former gdbinv-s.texi
+
+ * gdb.texinfo: use remote.texi rather than gdbinv-s.texi
+
+Wed Jul 28 08:26:24 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * gdbinv-s.texi: Documented timeout and retransmit-timeout
+ variables for MIPS remote debugging protocol.
+
+Mon Jul 26 13:00:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): FORTRAN LOGICAL fix.
+
+Tue Jul 20 16:30:41 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * Makefile.in (refcard.dvi): Use srcdir where necessary.
+
+Mon Jul 19 12:02:50 1993 Roland H. Pesch (pesch@cygnus.com)
+
+ * gdb.texinfo: repair conditional bugs in text markup
+
+Fri Jul 16 18:57:50 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, all-cfg.texi, h8-cfg.texi: introduce MOD2 switch
+ to select Modula-2 material.
+
+Thu Jul 15 13:15:01 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Cleanups regarding statics.
+
+ * gdbinv-s.texi (Bootstrapping): Document exceptionHandler.
+ (Debug Session): Mention exceptionHandler. Add xref to Bootstrapping.
+
+Mon Jul 12 13:37:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: N_MAIN is sometimes used for C.
+
+Fri Jul 9 09:47:02 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdbint.texinfo (Host, Target Conditionals): Remove TM_FILE_OVERRIDE.
+
+Tue Jul 6 12:41:28 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo (Target Conditionals): Remove NO_TYPEDEFS,
+ removed from the code by Kingdon.
+
+Tue Jul 6 12:24:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Break Commands): Remove stuff about flushing terminal
+ input when evaluating breakpoint conditions; the bug has been fixed.
+
+ * gdb.texinfo (Continuing and Stepping): Argument to "continue"
+ sets the ignore count to N-1, not to N.
+
+Thu Jul 1 14:57:42 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * refcard.tex (\hoffset): correct longstanding error to match
+ intended offset; avoids cutting off edge on some printers
+
+Wed Jun 30 18:23:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Parameters): Say that order of stabs is significant.
+
+Fri Jun 25 21:34:52 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Common Blocks): Say what Sun FORTRAN does.
+
+Fri Jun 25 16:15:10 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * Makefile.in: (REFEDITS) new var to control whether PS or CM
+ fonts and whether US or A4 paper for GDB refcard; (refcard.dvi)
+ collect sed edits if any, apply to refcard before formatting;
+ (refcard.ps) stop implying PS fonts if PS output requested;
+ (lrefcard.ps) delete extra target for variant PS fonts
+
+ * refcard.tex: parametrize papersize dependent info, collect
+ in easily replaced spot
+
+ * a4rc.sed: new file, edits to refcard for A4 paper
+
+Fri Jun 25 14:21:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Type -16 is 4 bytes.
+
+Wed Jun 23 15:02:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Minor character cleanups.
+
+Tue Jun 22 16:31:52 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Express disapproval of 'D' symbol descriptor
+ politely rather than rudely.
+
+Fri Jun 18 19:42:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Document common blocks.
+
+Fri Jun 18 12:12:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * stabs.texinfo: Add some basic info about stabs-in-elf.
+
+Fri Jun 18 13:57:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Top): Minor cleanup.
+
+Mon Jun 14 16:16:51 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com)
+
+ * Makefile.in (install-info): remove parentdir support
+
+Tue Jun 15 18:11:39 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo (Copying): delete this node and references to it;
+ RMS says this manual need not carry GPL. (passim): Improvements
+ from last round at FSF, largely due to Ian Taylor review, and
+ minor formatting improvements.
+
+ * gdbinv-s.texi (passim): Improvements from last round at FSF,
+ largely due to Ian Taylor review. (Debug Session): minor edits to
+ new text.
+
+Sun Jun 13 12:52:39 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (realclean): Remove info and dvi files too.
+
+Sat Jun 12 16:09:22 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * {all,h8}-config.texi: Rename to *-cfg.texi for 14 char filenames.
+ * Makefile.in: Change accordingly. gdb-config.texi -> gdb-cfg.texi.
+ * gdb.texinfo: Change accordingly.
+
+ * stabs.texinfo: Clean up N_{L,R}BRAC. Discuss what addresses of
+ N_{L,R}BRAC,N_SLINE are relative to.
+
+Fri Jun 11 15:15:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (GDBvn.texi): Update atomically.
+
+Wed Jun 9 10:58:16 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdbinv-s.texi (Debug Session): Document exceptionHook.
+
+Tue Jun 8 13:42:04 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.texinfo (Print Settings): Move all stuff relating to symbolic
+ addresses together. Also motivate the set print symbol-filename
+ command and suggest other solutions.
+
+Tue Jun 1 22:46:43 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.texinfo (set print elements): Note that the number of
+ elements is set to unlimited by "set print elements 0".
+
+Mon May 31 08:06:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Builtin Type Descriptors): Try to clarify what
+ NF_LDOUBLE means.
+ (Stab Types): Include Solaris stab types.
+ (Procedures): Document Solaris extensions.
+
+Thu May 27 06:20:42 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.texinfo: Add `set print symbol-filename' doc.
+
+Wed May 26 00:26:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Arrays): Talk about type definition vs. type
+ information.
+
+ * stabs.texinfo (Builtin Type Descriptors): Talk about omitting
+ the trailing semicolon.
+
+Tue May 25 14:49:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Line Numbers, Source Files): Re-write these two nodes
+ and merge in other parts of the document addressing these subjects.
+ gdbint.texinfo (XCOFF): Remove info which is now in stabs.texinfo.
+
+ * stabs.texinfo (Subranges, Arrays): Try to explain about the semicolon
+ at the end of a range type.
+
+ * stabs.texinfo (Subranges): "A offset" and "T offset" are not
+ AIX extensions.
+
+Mon May 24 09:00:33 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stabs Format): Misc fixes.
+
+Sat May 22 10:40:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Constants): Allow an `e' constant to be non-enum.
+ (Traditional builtin types): Document convex convention for long long.
+ (Negative builtin types): Discuss type names, and misc fixes.
+
+Fri May 21 11:20:31 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Builtin Type Descriptors): Document the floating
+ point types used with @samp{R} type descriptor.
+ (Symbol Descriptors): Describe how to handle conflict between
+ different meanings of @samp{P} symbol descriptor.
+
+Thu May 20 13:35:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Remove node Quick Reference and put its children
+ directly under the main menu.
+
+ * stabs.texinfo: Many more changes to bring it into line with
+ AIX documentation and reality. I think it now has all the
+ information from the AIX documentation, except that I burned
+ out when I got to variant records (Pascal and Modula-2) and
+ all the COBOL types. Oh well, we can add them later when we're
+ worrying more about those languages.
+
+ * stabs.texinfo (Automatic variables): Talk about what it means
+ to omit the symbol descriptor.
+
+Tue May 18 17:59:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Parameters): Add "(sometimes)" when describing
+ gcc2 behavior with promoted args.
+
+Fri May 14 21:35:29 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: include readline appendices in info version of manual
+
+Fri May 7 11:56:18 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdbinv-s.texi (Remote Serial): describe new ^C behavior in
+ target remote.
+
+ * gdb.texinfo (Machine Code): more index entries for disassemble
+
+Fri May 7 10:12:30 1993 Fred Fish (fnf@cygnus.com)
+
+ * Clarify the intended use of the gdb-testers and gdb-patches
+ mailing lists, and shrink gzip comment.
+
+Thu May 6 16:39:50 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo (Shell Commands): do not mention SHELL env var in
+ DOSHOST configuration of manual.
+
+ * gdb.texinfo (MIPS Stack): new node.
+
+ * all-config.texi (MIPS) new switch.
+
+ * gdbinv-s.texi (Nindy Options) Remove two instances of future
+ tense; (MIPS Remote) new node.
+
+ * gdb.texinfo (passim) rephrases to work around makeinfo @value
+ bug; (Environment) less passive, other small cleanups in text about
+ .cshrc/.bashrc; (Invoking GDB) new MIPS Remote menu entry;
+ (Remote) new MIPS Remote menu entry.
+
+Thu Apr 29 09:36:25 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo: Many changes to include information from the
+ AIX documentation.
+
+ * gdb.texinfo (Environment): Mention pitfall with .cshrc.
+
+Tue Apr 27 14:02:57 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdbint.texinfo (new node Debugging GDB, elsewhere):
+ Move a bunch of information from ../README.
+ (Getting Started): New node.
+
+Fri Apr 23 17:21:13 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdbinv-s.texi, gdb.texinfo: include Hitachi SH target
+
+ * gdb.texinfo: advance manual revision dates to present
+
+ * gdbinv-s.texi, gdb.texinfo, all-config.texi, h8-config.texi:
+ stop using silly Roman numerals in @set variable names
+
+Fri Apr 23 07:30:01 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Parameters): Keep trying to get this right.
+
+Wed Apr 21 15:18:47 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Parameters): More on "local parameters".
+
+Mon Apr 19 08:00:51 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Parameters): Re-do "local parameters" section.
+
+Sun Apr 18 09:47:45 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Symbol descriptors): Re-do using @table and @xref.
+ (Parameters): Rewrite.
+ (xcoff-differences, Sun-differences): Minor changes.
+
+Thu Apr 15 02:35:24 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * stabs.texinfo: Minor cleanup.
+
+Wed Apr 14 17:31:00 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdbint.texinfo: Minor xcoff stuff.
+
+Wed Apr 7 14:11:07 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdbint.texinfo: Update for new config directory structure.
+ Add info about internal type data structures.
+
+Mon Apr 5 09:06:30 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (SFILES_INCLUDED): gdb-config.texi is no longer in
+ $(srcdir).
+ (gdb-config.texi): Depend on file in $(srcdir).
+
+Fri Apr 2 16:55:13 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo: Fixes about N_SO.
+
+Fri Mar 26 18:00:35 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: include list of nonstandard init file names
+
+ * *-config.texi: new switch GENERIC for text that applies *only*
+ to (usual) multiple-target version of manual
+
+ * gdb.texinfo, gdbinv-s.texi: Update conditional markup to correct
+ h8 config
+
+ * gdb.texinfo: depend on latest fixed makeinfo, use conditionals
+ in menus (rather than conditionally selected multiple alternative
+ menus).
+
+ * Makefile.in: define and use DOC_CONFIG var to select
+ configuration for GDB user manual.
+
+ * gdb-config.texi: delete from repository, generate from Makefile.
+
+ * all-config.texi: normal `generic' configuration file, formerly
+ stored as gdb-config.texi
+
+Wed Mar 24 14:03:19 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: add dvi target to build all .dvi files
+
+Tue Mar 23 16:03:24 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, gdvinv-s.texinfo: formatting improvements.
+
+Fri Mar 19 21:46:50 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Doc NO_MMALLOC and NO_MMALLOC_CHECK as
+ host conditionals.
+ * stabs.texinfo: More array fixes inspired by Jim's.
+
+Fri Mar 19 10:23:34 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo: Fixes re arrays and continuations.
+
+ * gdbint.texinfo: Add XCOFF node.
+
+Mon Mar 8 15:52:18 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo: Add `set print max-symbolic-offset' doc.
+
+Sun Feb 21 17:09:38 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * stabs.texinfo: Fix for array types to mention lower bounds.
+
+Thu Feb 18 01:19:49 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Update PTRACE_ARG3_TYPE doc, pull PT_*.
+
+Wed Feb 17 08:15:24 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Remove SET_STACK_LIMIT_HUGE from target defines.
+
+Thu Feb 11 10:38:40 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Fix thinko (NM_FILE => NAT_FILE). Found
+ by Michael Ben-Gershon <mybg@CS.HUJI.AC.IL>.
+
+Wed Feb 10 23:59:19 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Eliminate IBM6000_HOST, document IBM6000_TARGET.
+
+Tue Feb 9 18:26:21 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, gdbinv-s.texi: misc updates
+
+Sat Feb 6 10:25:47 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Brief documentation for longjmp support,
+ from an email msg by Stu.
+
+Fri Feb 5 14:10:15 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Fix description of floating point "range"
+ types (which really define basic types). Reported by Jim Meehan,
+ <meehan@src.dec.com>.
+
+ * gdbint.texinfo: Remove COFF_NO_LONG_FILE_NAMES define, now gone.
+
+Thu Feb 4 13:56:46 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * gdbint.texinfo: Slightly expand section on supporting a new
+ object file format.
+
+Thu Feb 4 01:49:04 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (refcard.ps, lrefcard.ps): Remove psref.tex
+ intermediate file.
+
+Tue Feb 2 12:18:06 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, gdbinv-s.texi: miscellaneous stylistic cleanups
+
+Mon Feb 1 15:35:47 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdbinv-s.texi: z8000 simulator target name is just "sim"
+
+ * gdbinv-s.texi: Mention that Z8000 simulator can simulate Z8001
+ as well as Z8002.
+
+Sat Nov 28 06:51:35 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Add sections on clean design and on how to send
+ in changes.
+
+Mon Nov 9 23:57:02 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Add how to declare the result of make_cleanup.
+
+Mon Oct 26 11:09:47 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo: Fix typo, reported by Karl Berry.
+
+Fri Oct 23 00:41:21 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo: Add opcodes dir to GDB distribution description.
+
+Sat Oct 10 18:04:58 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * gdbint.texinfo: fixed a stray email address (needs @@),
+ added @table @code to node "Native Conditionals"
+
+Tue Sep 22 00:34:15 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Describe coding style of GDB.
+
+Mon Sep 21 19:32:16 1992 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Minor wording changes.
+
+Tue Sep 15 02:57:09 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Improve release doc slightly.
+
+Fri Sep 11 01:34:25 1992 John Gilmore (gnu@sphagnum.cygnus.com)
+
+ * gdbint.texinfo: Improve doc of GDB config macros.
+
+Wed Sep 9 16:52:06 1992 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Remove Bothner's changes for C++ nested types.
+ These will be reinserted when examined.
+
+Mon Aug 24 01:17:55 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Make a start at documenting all the #if macros
+ in GDB. At least list them all, and start separating them into
+ host-specific and target-specific.
+
+Tue Aug 18 15:59:13 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdbinv-s.m4.in: refrain from using @cartouche for just a few
+ examples (not consistent w others).
+ gdb.texinfo: issue disclaimer paragraph on cmdline options only
+ for generic vn of doc
+
+Tue Aug 18 14:53:27 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: always create installation directories.
+
+Tue Aug 18 14:11:50 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: in h8 config, do not describe searching commands.
+
+Mon Aug 17 18:07:59 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, none.m4, h8.m4, gdbinv-s.m4.in: improve H8/300
+ conditionals; introduce a few generic switches that may be
+ useful for other cross-dev or dos-hosted configs.
+
+ * gdb.texinfo: fix typo in "info reg" description
+
+Sun Aug 16 01:16:18 1992 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Minor updates from running TeX over it.
+ * Makefile.in (stabs.dvi, stabs.ps): Add.
+
+Sat Aug 15 20:52:24 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * stabs.texinfo: Stabs documentation, written by Julia Menapace.
+ First pass at converting it to texinfo.
+
+Sat Aug 15 03:14:59 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo, refcard.tex: Document mult args on `info reg'.
+ * Makefile.in (refcard.ps, lrefcard.ps): Add missing $(srdir).
+
+Fri Aug 14 21:08:47 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Add section on partial symbol tables.
+
+Sat Jun 20 16:31:10 1992 John Gilmore (gnu at cygnus.com)
+
+ * gdb.texinfo: document `set remotedebug' and `set
+ rstack_high_address'.
+
+Thu May 14 17:09:48 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: slight expansion of new text on reading info files
+ * gdbinv-s.m4.in: correct and expand info on cross-debugging
+ H8/300 from DOS.
+
+Tue May 12 12:22:47 1992 John Gilmore (gnu at cygnus.com)
+
+ * gdb.texinfo: `info user' => `show user'. Noticed by David Taylor.
+
+Mon May 11 19:06:27 1992 John Gilmore (gnu at cygnus.com)
+
+ * gdb.texinfo: Say how to read the `info' files.
+
+Tue May 5 12:11:38 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: gm4 -> m4.
+
+Fri Apr 10 17:50:43 1992 John Gilmore (gnu at rtl.cygnus.com)
+
+ * gdb.texinfo: Update for GDB-4.5. Move `Formatting
+ Documentation' ahead of `Installing GDB' to match README.
+ Update shared library doc, -readnow and -mapped, and directory
+ structure (add glob and mmalloc). Update configure doc.
+
+Tue Mar 24 23:28:38 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: remove $(srcdir) from gdb.info rule.
+
+Sat Mar 7 18:44:50 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: commented out gdb-all.texinfo rule. This is
+ temporary.
+
+Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in: removed traces of namesubdir,
+ -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced
+ copyrights to '92, changed some from Cygnus to FSF.
+
+Fri Dec 13 09:47:31 1991 John Gilmore (gnu at cygnus.com)
+
+ * gdb.texinfo: Improve how we ask for bug reports.
+
+Tue Dec 10 04:07:21 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: infodir belongs in datadir.
+
+Fri Dec 6 23:57:34 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: remove spaces following hyphens, bsd make can't
+ cope. install using INSTALL_DATA. added clean-info. added
+ standards.text support.
+
+Thu Dec 5 22:46:12 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: idestdir and ddestdir go away. Added copyrights
+ and shift gpl to v2. Added ChangeLog if it didn't exist. docdir
+ and mandir now keyed off datadir by default.
+
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/gnu/usr.bin/gdb/doc/Makefile b/gnu/usr.bin/gdb/doc/Makefile
new file mode 100644
index 000000000000..8cde5d4b5350
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/Makefile
@@ -0,0 +1,340 @@
+# This file was generated automatically by configure. Do not edit.
+VPATH = .
+links =
+host_alias = i386-unknown-freebsd
+host_cpu = i386
+host_vendor = unknown
+host_os = freebsd
+host_canonical = i386-unknown-freebsd
+target_alias = i386-unknown-freebsd
+target_cpu = i386
+target_vendor = unknown
+target_os = freebsd
+target_canonical = i386-unknown-freebsd
+##Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+# Makefile for GDB documentation.
+# 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+srcdir = .
+
+prefix = /usr/gnu
+
+infodir = $(prefix)/info
+
+SHELL = /bin/sh
+
+INSTALL = install -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+
+# main GDB source directory
+gdbdir = $(srcdir)/..
+
+# where to find texinfo; GDB dist should include a recent one
+TEXIDIR=${gdbdir}/../texinfo
+
+# where to find makeinfo, preferably one designed for texinfo-2
+MAKEINFO=makeinfo
+
+# where to find texi2roff, ditto
+TEXI2ROFF=texi2roff
+
+# Where is the source dir for the READLINE library doc?
+# Traditionally readline is in .. or .
+READLINE_DIR = ${gdbdir}/../readline/doc
+
+SET_TEXINPUTS = TEXINPUTS=${TEXIDIR}:.:$(srcdir):$(READLINE_DIR):$$TEXINPUTS
+
+# There may be alternate predefined collections of switches to configure
+# the GDB manual. Normally this is not done in synch with the software
+# config system, since this choice tends to be independent; most people
+# want a doc config of `all' for a generic manual, regardless of sw config.
+DOC_CONFIG = all
+
+# This list of sed edits will edit the GDB reference card
+# for what fonts and what papersize to use.
+# By default (NO edits applied), the refcard uses:
+# - Computer Modern (CM) fonts
+# - US letter paper (8.5x11in)
+# List some of the following files for alternative fonts and paper:
+# a4rc.sed use A4 paper (297 x 210 mm)
+# psrc.sed use PostScript fonts (Karl Berry short TeX names)
+# lpsrc.sed use PostScript fonts (full PostScript names in TeX)
+# e.g. for A4, Postscript: REFEDITS = a4rc.sed psrc.sed
+# for A4, CM fonts: REFEDITS = a4rc.sed
+# for US, PS fonts: REFEDITS = psrc.sed
+# for default:
+REFEDITS =
+
+# Don Knuth's TeX formatter
+TEX = tex
+
+# auxiliary program for sorting Texinfo indices
+TEXINDEX = texindex
+
+# Main GDB manual's source files
+SFILES_INCLUDED = gdb-cfg.texi $(srcdir)/remote.texi
+
+SFILES_LOCAL = $(srcdir)/gdb.texinfo GDBvn.texi $(SFILES_INCLUDED)
+
+SFILES_DOC = $(SFILES_LOCAL) \
+ $(READLINE_DIR)/rluser.texinfo $(READLINE_DIR)/inc-hist.texi
+
+#### Host, target, and site specific Makefile fragments come in here.
+###
+
+all install:
+
+info: gdb.info gdbint.info stabs.info
+dvi: gdb.dvi refcard.dvi gdbint.dvi
+all-doc: gdb.info gdb.dvi refcard.dvi gdb-internals gdbint.dvi
+
+install-info: info
+ for i in *.info* ; do \
+ $(INSTALL_DATA) $$i $(infodir)/$$i ; \
+ done
+
+STAGESTUFF = *.info* gdb-all.texi GDBvn.texi
+
+# Copy the object files from a particular stage into a subdirectory.
+stage1: force
+ -mkdir stage1
+ -mv $(STAGESTUFF) stage1
+
+stage2: force
+ -mkdir stage2
+ -mv $(STAGESTUFF) stage2
+
+stage3: force
+ -mkdir stage3
+ -mv $(STAGESTUFF) stage3
+
+against=stage2
+
+comparison: force
+ for i in $(STAGESTUFF) ; do cmp $$i $(against)/$$i ; done
+
+de-stage1: force
+ -(cd stage1 ; mv -f * ..)
+ -rmdir stage1
+
+de-stage2: force
+ -(cd stage2 ; mv -f * ..)
+ -rmdir stage2
+
+de-stage3: force
+ -(cd stage3 ; mv -f * ..)
+ -rmdir stage3
+
+clean-info:
+ rm -f gdb.info* gdbint.info* stabs.info*
+
+clean-dvi:
+ rm -f gdb.dvi refcard.dvi gdbint.dvi stabs.dvi sedref.dvi
+
+mostlyclean: clean-info clean-dvi
+ rm -f gdb.?? gdb.??? gdb.mm gdb.ms gdb.me
+ rm -f links2roff
+ rm -f refcard.ps lrefcard.ps refcard.log sedref.* *~
+ rm -f gdbint.?? gdbint.??? stabs.?? stabs.???
+
+clean: mostlyclean
+ rm -f GDBvn.texi rluser.texinfo inc-hist.texi
+
+distclean: clean
+ rm -f Makefile config.status
+
+realclean: distclean clean-dvi clean-info
+
+# GDB QUICK REFERENCE (dvi output)
+refcard.dvi : refcard.tex $(REFEDITS)
+ if [ -z "$(REFEDITS)" ]; then \
+ cp $(srcdir)/refcard.tex sedref.tex ; \
+ else \
+ echo > tmp.sed ; \
+ for f in "$(REFEDITS)" ; do \
+ cat $(srcdir)/$$f >>tmp.sed ; done ; \
+ sed -f tmp.sed $(srcdir)/refcard.tex >sedref.tex ; \
+ fi
+ $(SET_TEXINPUTS) $(TEX) sedref.tex
+ mv sedref.dvi refcard.dvi
+ rm -f sedref.log sedref.tex tmp.sed
+
+refcard.ps : refcard.dvi
+ dvips -t landscape refcard.dvi -o
+
+# File to record current GDB version number (copied from main dir Makefile.in)
+GDBvn.texi : ${gdbdir}/Makefile.in
+ echo "@set GDBVN `sed <$(srcdir)/../Makefile.in -n 's/VERSION = //p'`" > ./GDBvn.new
+ mv GDBvn.new GDBvn.texi
+
+# Updated atomically
+.PRECIOUS: GDBvn.texi
+
+# Choose configuration for GDB manual (normally `all'; normally not tied into
+# `configure' script because most users prefer generic version of manual,
+# not one for their binary config---which may not be specifically
+# defined anyways).
+gdb-cfg.texi: ${srcdir}/${DOC_CONFIG}-cfg.texi
+ ln -s ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi || \
+ ln ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi || \
+ cp ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi
+
+# GDB MANUAL: texinfo source, using @set/@clear/@value/@ifset/@ifclear
+# If your texinfo or makeinfo don't support these, get a new texinfo release
+#
+# The nonsense with GDBvn.texi gets this to run with both Sun and GNU make.
+# Note that we can *generate* GDBvn.texi, but since we distribute one in the
+# source directory for the benefit of people who *don't* use this makefile,
+# VPATH will often tell make not to bother building it, because the one
+# in the srcdir is up to date. (if not, then make should build one here).
+
+# GDB MANUAL: TeX dvi file
+gdb.dvi: ${SFILES_DOC}
+ if [ ! -f ./GDBvn.texi ]; then \
+ ln -s $(srcdir)/GDBvn.texi . || \
+ ln $(srcdir)/GDBvn.texi . || \
+ cp $(srcdir)/GDBvn.texi . ; else true; fi
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ $(TEXINDEX) gdb.??
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ rm -f gdb.?? gdb.log gdb.aux gdb.toc gdb.??s
+
+# GDB MANUAL: info file
+# We're using texinfo2, and older makeinfo's may not be able to
+# cope with all the markup.
+gdb.info: ${SFILES_DOC}
+ $(MAKEINFO) -I ${READLINE_DIR} -I $(srcdir) -o ./gdb.info gdb.texinfo
+
+# GDB MANUAL: roff translations
+# Try to use a recent texi2roff. v2 was put on prep in jan91.
+# If you want an index, see texi2roff doc for postprocessing
+# and add -i to texi2roff invocations below.
+# Workarounds for texi2roff-2 (probably fixed in later texi2roff's, delete
+# corresponding -e lines when later texi2roff's are current)
+# + @ifinfo's deleted explicitly due to texi2roff-2 bug w nested constructs.
+# + @c's deleted explicitly because texi2roff sees texinfo commands in them
+# + @ (that's at-BLANK) not recognized by texi2roff, turned into blank
+# + @alphaenumerate is ridiculously new, turned into @enumerate
+
+# texi2roff doesn't have a notion of include dirs, so we have to fake
+# it out for gdb manual's include files---but only if not configured
+# in main sourcedir.
+links2roff: $(SFILES_INCLUDED)
+ if [ ! -f gdb.texinfo ]; then \
+ ln -s $(SFILES_INCLUDED) . || \
+ ln $(SFILES_INCLUDED) . || \
+ cp $(SFILES_INCLUDED) . ; \
+ fi
+ touch links2roff
+
+# "Readline" appendices. Get them also due to lack of includes,
+# regardless of whether or not configuring in main sourcedir.
+# @ftable removed due to bug in texi2roff-2; if your texi2roff
+# is newer, try just ln or cp
+rluser.texinfo: ${READLINE_DIR}/rluser.texinfo
+ sed -e 's/^@ftable/@table/g' \
+ -e 's/^@end ftable/@end table/g' \
+ ${READLINE_DIR}/rluser.texinfo > ./rluser.texinfo
+
+inc-hist.texi: ${READLINE_DIR}/inc-hist.texi
+ ln -s ${READLINE_DIR}/inc-hist.texi . || \
+ ln ${READLINE_DIR}/inc-hist.texi . || \
+ cp ${READLINE_DIR}/inc-hist.texi .
+
+# gdb manual suitable for [gtn]roff -me
+gdb.me: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -me | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.me
+
+# gdb manual suitable for [gtn]roff -ms
+gdb.ms: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -ms | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.ms
+
+# gdb manual suitable for [tn]roff -mm
+# '@noindent's removed due to texi2roff-2 mm bug; if yours is newer,
+# try leaving them in
+gdb.mm: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e '/@noindent/d' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -mm | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.mm
+
+# GDB INTERNALS MANUAL: TeX dvi file
+gdbint.dvi : gdbint.texinfo
+ $(SET_TEXINPUTS) $(TEX) gdbint.texinfo
+ $(TEXINDEX) gdbint.??
+ $(SET_TEXINPUTS) $(TEX) gdbint.texinfo
+ rm -f gdbint.?? gdbint.aux gdbint.cps gdbint.fns gdbint.kys \
+ gdbint.log gdbint.pgs gdbint.toc gdbint.tps gdbint.vrs
+
+# GDB INTERNALS MANUAL: info file
+gdb-internals: gdbint.info
+
+gdbint.info: gdbint.texinfo
+ $(MAKEINFO) -o gdbint.info $(srcdir)/gdbint.texinfo
+
+stabs.info: stabs.texinfo
+ $(MAKEINFO) -o stabs.info $(srcdir)/stabs.texinfo
+
+# STABS DOCUMENTATION: TeX dvi file
+stabs.dvi : stabs.texinfo
+ $(SET_TEXINPUTS) $(TEX) stabs.texinfo
+ $(TEXINDEX) stabs.??
+ $(SET_TEXINPUTS) $(TEX) stabs.texinfo
+ rm -f stabs.?? stabs.aux stabs.cps stabs.fns stabs.kys \
+ stabs.log stabs.pgs stabs.toc stabs.tps stabs.vrs
+
+stabs.ps: stabs.dvi
+ dvips -o stabs.ps stabs
+
+force:
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
diff --git a/gnu/usr.bin/gdb/doc/Makefile.in b/gnu/usr.bin/gdb/doc/Makefile.in
new file mode 100644
index 000000000000..d5ae2904f700
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/Makefile.in
@@ -0,0 +1,327 @@
+##Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+# Makefile for GDB documentation.
+# 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 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+srcdir = .
+
+prefix = /usr/local
+
+infodir = $(prefix)/info
+
+SHELL = /bin/sh
+
+INSTALL = install -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+
+# main GDB source directory
+gdbdir = $(srcdir)/..
+
+# where to find texinfo; GDB dist should include a recent one
+TEXIDIR=${gdbdir}/../texinfo
+
+# where to find makeinfo, preferably one designed for texinfo-2
+MAKEINFO=makeinfo
+
+# where to find texi2roff, ditto
+TEXI2ROFF=texi2roff
+
+# Where is the source dir for the READLINE library doc?
+# Traditionally readline is in .. or .
+READLINE_DIR = ${gdbdir}/../readline/doc
+
+SET_TEXINPUTS = TEXINPUTS=${TEXIDIR}:.:$(srcdir):$(READLINE_DIR):$$TEXINPUTS
+
+# There may be alternate predefined collections of switches to configure
+# the GDB manual. Normally this is not done in synch with the software
+# config system, since this choice tends to be independent; most people
+# want a doc config of `all' for a generic manual, regardless of sw config.
+DOC_CONFIG = all
+
+# This list of sed edits will edit the GDB reference card
+# for what fonts and what papersize to use.
+# By default (NO edits applied), the refcard uses:
+# - Computer Modern (CM) fonts
+# - US letter paper (8.5x11in)
+# List some of the following files for alternative fonts and paper:
+# a4rc.sed use A4 paper (297 x 210 mm)
+# psrc.sed use PostScript fonts (Karl Berry short TeX names)
+# lpsrc.sed use PostScript fonts (full PostScript names in TeX)
+# e.g. for A4, Postscript: REFEDITS = a4rc.sed psrc.sed
+# for A4, CM fonts: REFEDITS = a4rc.sed
+# for US, PS fonts: REFEDITS = psrc.sed
+# for default:
+REFEDITS =
+
+# Don Knuth's TeX formatter
+TEX = tex
+
+# auxiliary program for sorting Texinfo indices
+TEXINDEX = texindex
+
+# Main GDB manual's source files
+SFILES_INCLUDED = gdb-cfg.texi $(srcdir)/remote.texi
+
+SFILES_LOCAL = $(srcdir)/gdb.texinfo GDBvn.texi $(SFILES_INCLUDED)
+
+SFILES_DOC = $(SFILES_LOCAL) \
+ $(READLINE_DIR)/rluser.texinfo $(READLINE_DIR)/inc-hist.texi
+
+#### Host, target, and site specific Makefile fragments come in here.
+###
+
+all install:
+
+info: gdb.info gdbint.info stabs.info
+dvi: gdb.dvi refcard.dvi gdbint.dvi
+all-doc: gdb.info gdb.dvi refcard.dvi gdb-internals gdbint.dvi
+
+install-info: info
+ for i in *.info* ; do \
+ $(INSTALL_DATA) $$i $(infodir)/$$i ; \
+ done
+
+STAGESTUFF = *.info* gdb-all.texi GDBvn.texi
+
+# Copy the object files from a particular stage into a subdirectory.
+stage1: force
+ -mkdir stage1
+ -mv $(STAGESTUFF) stage1
+
+stage2: force
+ -mkdir stage2
+ -mv $(STAGESTUFF) stage2
+
+stage3: force
+ -mkdir stage3
+ -mv $(STAGESTUFF) stage3
+
+against=stage2
+
+comparison: force
+ for i in $(STAGESTUFF) ; do cmp $$i $(against)/$$i ; done
+
+de-stage1: force
+ -(cd stage1 ; mv -f * ..)
+ -rmdir stage1
+
+de-stage2: force
+ -(cd stage2 ; mv -f * ..)
+ -rmdir stage2
+
+de-stage3: force
+ -(cd stage3 ; mv -f * ..)
+ -rmdir stage3
+
+clean-info:
+ rm -f gdb.info* gdbint.info* stabs.info*
+
+clean-dvi:
+ rm -f gdb.dvi refcard.dvi gdbint.dvi stabs.dvi sedref.dvi
+
+mostlyclean: clean-info clean-dvi
+ rm -f gdb.?? gdb.??? gdb.mm gdb.ms gdb.me
+ rm -f links2roff
+ rm -f refcard.ps lrefcard.ps refcard.log sedref.* *~
+ rm -f gdbint.?? gdbint.??? stabs.?? stabs.???
+
+clean: mostlyclean
+ rm -f GDBvn.texi rluser.texinfo inc-hist.texi
+
+distclean: clean
+ rm -f Makefile config.status
+
+realclean: distclean clean-dvi clean-info
+
+# GDB QUICK REFERENCE (dvi output)
+refcard.dvi : refcard.tex $(REFEDITS)
+ if [ -z "$(REFEDITS)" ]; then \
+ cp $(srcdir)/refcard.tex sedref.tex ; \
+ else \
+ echo > tmp.sed ; \
+ for f in "$(REFEDITS)" ; do \
+ cat $(srcdir)/$$f >>tmp.sed ; done ; \
+ sed -f tmp.sed $(srcdir)/refcard.tex >sedref.tex ; \
+ fi
+ $(SET_TEXINPUTS) $(TEX) sedref.tex
+ mv sedref.dvi refcard.dvi
+ rm -f sedref.log sedref.tex tmp.sed
+
+refcard.ps : refcard.dvi
+ dvips -t landscape refcard.dvi -o
+
+# File to record current GDB version number (copied from main dir Makefile.in)
+GDBvn.texi : ${gdbdir}/Makefile.in
+ echo "@set GDBVN `sed <$(srcdir)/../Makefile.in -n 's/VERSION = //p'`" > ./GDBvn.new
+ mv GDBvn.new GDBvn.texi
+
+# Updated atomically
+.PRECIOUS: GDBvn.texi
+
+# Choose configuration for GDB manual (normally `all'; normally not tied into
+# `configure' script because most users prefer generic version of manual,
+# not one for their binary config---which may not be specifically
+# defined anyways).
+gdb-cfg.texi: ${srcdir}/${DOC_CONFIG}-cfg.texi
+ ln -s ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi || \
+ ln ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi || \
+ cp ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi
+
+# GDB MANUAL: texinfo source, using @set/@clear/@value/@ifset/@ifclear
+# If your texinfo or makeinfo don't support these, get a new texinfo release
+#
+# The nonsense with GDBvn.texi gets this to run with both Sun and GNU make.
+# Note that we can *generate* GDBvn.texi, but since we distribute one in the
+# source directory for the benefit of people who *don't* use this makefile,
+# VPATH will often tell make not to bother building it, because the one
+# in the srcdir is up to date. (if not, then make should build one here).
+
+# GDB MANUAL: TeX dvi file
+gdb.dvi: ${SFILES_DOC}
+ if [ ! -f ./GDBvn.texi ]; then \
+ ln -s $(srcdir)/GDBvn.texi . || \
+ ln $(srcdir)/GDBvn.texi . || \
+ cp $(srcdir)/GDBvn.texi . ; else true; fi
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ $(TEXINDEX) gdb.??
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ rm -f gdb.?? gdb.log gdb.aux gdb.toc gdb.??s
+
+# GDB MANUAL: info file
+# We're using texinfo2, and older makeinfo's may not be able to
+# cope with all the markup.
+gdb.info: ${SFILES_DOC}
+ $(MAKEINFO) -I ${READLINE_DIR} -I $(srcdir) -o ./gdb.info gdb.texinfo
+
+# GDB MANUAL: roff translations
+# Try to use a recent texi2roff. v2 was put on prep in jan91.
+# If you want an index, see texi2roff doc for postprocessing
+# and add -i to texi2roff invocations below.
+# Workarounds for texi2roff-2 (probably fixed in later texi2roff's, delete
+# corresponding -e lines when later texi2roff's are current)
+# + @ifinfo's deleted explicitly due to texi2roff-2 bug w nested constructs.
+# + @c's deleted explicitly because texi2roff sees texinfo commands in them
+# + @ (that's at-BLANK) not recognized by texi2roff, turned into blank
+# + @alphaenumerate is ridiculously new, turned into @enumerate
+
+# texi2roff doesn't have a notion of include dirs, so we have to fake
+# it out for gdb manual's include files---but only if not configured
+# in main sourcedir.
+links2roff: $(SFILES_INCLUDED)
+ if [ ! -f gdb.texinfo ]; then \
+ ln -s $(SFILES_INCLUDED) . || \
+ ln $(SFILES_INCLUDED) . || \
+ cp $(SFILES_INCLUDED) . ; \
+ fi
+ touch links2roff
+
+# "Readline" appendices. Get them also due to lack of includes,
+# regardless of whether or not configuring in main sourcedir.
+# @ftable removed due to bug in texi2roff-2; if your texi2roff
+# is newer, try just ln or cp
+rluser.texinfo: ${READLINE_DIR}/rluser.texinfo
+ sed -e 's/^@ftable/@table/g' \
+ -e 's/^@end ftable/@end table/g' \
+ ${READLINE_DIR}/rluser.texinfo > ./rluser.texinfo
+
+inc-hist.texi: ${READLINE_DIR}/inc-hist.texi
+ ln -s ${READLINE_DIR}/inc-hist.texi . || \
+ ln ${READLINE_DIR}/inc-hist.texi . || \
+ cp ${READLINE_DIR}/inc-hist.texi .
+
+# gdb manual suitable for [gtn]roff -me
+gdb.me: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -me | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.me
+
+# gdb manual suitable for [gtn]roff -ms
+gdb.ms: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -ms | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.ms
+
+# gdb manual suitable for [tn]roff -mm
+# '@noindent's removed due to texi2roff-2 mm bug; if yours is newer,
+# try leaving them in
+gdb.mm: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e '/@noindent/d' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -mm | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.mm
+
+# GDB INTERNALS MANUAL: TeX dvi file
+gdbint.dvi : gdbint.texinfo
+ $(SET_TEXINPUTS) $(TEX) gdbint.texinfo
+ $(TEXINDEX) gdbint.??
+ $(SET_TEXINPUTS) $(TEX) gdbint.texinfo
+ rm -f gdbint.?? gdbint.aux gdbint.cps gdbint.fns gdbint.kys \
+ gdbint.log gdbint.pgs gdbint.toc gdbint.tps gdbint.vrs
+
+# GDB INTERNALS MANUAL: info file
+gdb-internals: gdbint.info
+
+gdbint.info: gdbint.texinfo
+ $(MAKEINFO) -o gdbint.info $(srcdir)/gdbint.texinfo
+
+stabs.info: stabs.texinfo
+ $(MAKEINFO) -o stabs.info $(srcdir)/stabs.texinfo
+
+# STABS DOCUMENTATION: TeX dvi file
+stabs.dvi : stabs.texinfo
+ $(SET_TEXINPUTS) $(TEX) stabs.texinfo
+ $(TEXINDEX) stabs.??
+ $(SET_TEXINPUTS) $(TEX) stabs.texinfo
+ rm -f stabs.?? stabs.aux stabs.cps stabs.fns stabs.kys \
+ stabs.log stabs.pgs stabs.toc stabs.tps stabs.vrs
+
+stabs.ps: stabs.dvi
+ dvips -o stabs.ps stabs
+
+force:
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
diff --git a/gnu/usr.bin/gdb/doc/a4rc.sed b/gnu/usr.bin/gdb/doc/a4rc.sed
new file mode 100644
index 000000000000..22922904efc9
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/a4rc.sed
@@ -0,0 +1,11 @@
+/--- Papersize params:/,/--- end papersize params/c\
+%------- Papersize params:\
+%% A4 paper (297x210mm)\
+%%\
+\\totalwidth=297mm % total width of paper\
+\\totalheight=210mm % total height of paper\
+\\hmargin=5mm % horizontal margin width\
+\\vmargin=10mm % vertical margin width\
+\\secskip=.6pc % space between refcard secs\
+\\lskip=1pt % extra skip between \\sec entries\
+%------- end papersize params
diff --git a/gnu/usr.bin/gdb/doc/all-cfg.texi b/gnu/usr.bin/gdb/doc/all-cfg.texi
new file mode 100644
index 000000000000..ec64da105ed3
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/all-cfg.texi
@@ -0,0 +1,117 @@
+@c GDB MANUAL configuration file.
+@c Copyright (c) 1993 Free Software Foundation, Inc.
+@c
+@c NOTE: While the GDB manual is configurable (by changing these
+@c switches), its configuration is ***NOT*** automatically tied in to
+@c source configuration---because the authors expect that, save in
+@c unusual cases, the most inclusive form of the manual is appropriate
+@c no matter how the program itself is configured.
+@c
+@c The only automatically-varying variable is the GDB version number,
+@c which the Makefile rewrites based on the VERSION variable from
+@c `../Makefile.in'.
+@c
+@c GDB version number is recorded in the variable GDBVN
+@include GDBvn.texi
+@c
+@c ----------------------------------------------------------------------
+@c PLATFORM FLAGS:
+@set GENERIC
+@c
+@c Hitachi H8/300 target:
+@set H8
+@c Hitachi H8/300 target ONLY:
+@clear H8EXCLUSIVE
+@c
+@c remote MIPS target:
+@set MIPS
+@c
+@c SPARC target:
+@set SPARC
+@c
+@c AMD 29000 target:
+@set AMD29K
+@c
+@c Intel 960 target:
+@set I960
+@c
+@c Tandem ST2000 (phone switch) target:
+@set ST2000
+@c
+@c Zilog 8000 target:
+@set Z8K
+@c
+@c Lucid "Energize" environment:
+@clear LUCID
+@c
+@c Wind River Systems VxWorks environment:
+@set VXWORKS
+@c
+@c ----------------------------------------------------------------------
+@c DOC FEATURE FLAGS:
+@c
+@c Include change-from-old?
+@set NOVEL
+@c
+@c Bare-board target?
+@clear BARETARGET
+@c
+@c Restrict languages discussed to C?
+@c This is backward. As time permits, change this to language-specific
+@c switches for what to include.
+@clear CONLY
+@c Discuss Fortran?
+@set FORTRAN
+@c
+@c Discuss Modula 2?
+@set MOD2
+@c
+@c Specifically for host machine running DOS?
+@clear DOSHOST
+@c
+@c Talk about CPU simulator targets?
+@set SIMS
+@c
+@c Is manual stand-alone, or part of an agglomeration, with overall GPL?
+@clear AGGLOMERATION
+@c
+@c Remote serial line settings of interest?
+@set SERIAL
+@c
+@c Discuss features requiring Posix or similar OS environment?
+@set POSIX
+@c
+@c Discuss remote serial debugging stub?
+@set REMOTESTUB
+@c
+@c Discuss gdbserver?
+@set GDBSERVER
+@c
+@c Refrain from discussing how to configure sw and format doc?
+@clear PRECONFIGURED
+@c
+@c Refrain from referring to unfree publications?
+@set FSFDOC
+@c
+@c ----------------------------------------------------------------------
+@c STRINGS:
+@c
+@c Name of GDB program. Used also for (gdb) prompt string.
+@set GDBP gdb
+@c
+@c Name of GDB product. Used in running text.
+@set GDBN GDB
+@c
+@c Name of GDB initialization file.
+@set GDBINIT .gdbinit
+@c
+@c Name of host. Should not be used in generic configs, but generic
+@c value may catch some flubs.
+@set HOST machine specific
+@c
+@c Name of GCC product
+@set NGCC GCC
+@c
+@c Name of GCC program
+@set GCC gcc
+
diff --git a/gnu/usr.bin/gdb/doc/config.status b/gnu/usr.bin/gdb/doc/config.status
new file mode 100755
index 000000000000..5d2c6dd679a3
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/config.status
@@ -0,0 +1,5 @@
+#!/bin/sh
+# This file was generated automatically by configure. Do not edit.
+# This directory was configured as follows:
+../../configure --host=i386-unknown-freebsd --target=i386-unknown-freebsd -norecursion
+#
diff --git a/gnu/usr.bin/gdb/doc/configure.in b/gnu/usr.bin/gdb/doc/configure.in
new file mode 100644
index 000000000000..1d2b47e78cc5
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/configure.in
@@ -0,0 +1,7 @@
+srcname="GDB doc"
+srctrigger=gdb.texinfo
+# per-host:
+# per-target:
+
+files=""
+links=""
diff --git a/gnu/usr.bin/gdb/doc/gdb-cfg.texi b/gnu/usr.bin/gdb/doc/gdb-cfg.texi
new file mode 100644
index 000000000000..ec64da105ed3
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb-cfg.texi
@@ -0,0 +1,117 @@
+@c GDB MANUAL configuration file.
+@c Copyright (c) 1993 Free Software Foundation, Inc.
+@c
+@c NOTE: While the GDB manual is configurable (by changing these
+@c switches), its configuration is ***NOT*** automatically tied in to
+@c source configuration---because the authors expect that, save in
+@c unusual cases, the most inclusive form of the manual is appropriate
+@c no matter how the program itself is configured.
+@c
+@c The only automatically-varying variable is the GDB version number,
+@c which the Makefile rewrites based on the VERSION variable from
+@c `../Makefile.in'.
+@c
+@c GDB version number is recorded in the variable GDBVN
+@include GDBvn.texi
+@c
+@c ----------------------------------------------------------------------
+@c PLATFORM FLAGS:
+@set GENERIC
+@c
+@c Hitachi H8/300 target:
+@set H8
+@c Hitachi H8/300 target ONLY:
+@clear H8EXCLUSIVE
+@c
+@c remote MIPS target:
+@set MIPS
+@c
+@c SPARC target:
+@set SPARC
+@c
+@c AMD 29000 target:
+@set AMD29K
+@c
+@c Intel 960 target:
+@set I960
+@c
+@c Tandem ST2000 (phone switch) target:
+@set ST2000
+@c
+@c Zilog 8000 target:
+@set Z8K
+@c
+@c Lucid "Energize" environment:
+@clear LUCID
+@c
+@c Wind River Systems VxWorks environment:
+@set VXWORKS
+@c
+@c ----------------------------------------------------------------------
+@c DOC FEATURE FLAGS:
+@c
+@c Include change-from-old?
+@set NOVEL
+@c
+@c Bare-board target?
+@clear BARETARGET
+@c
+@c Restrict languages discussed to C?
+@c This is backward. As time permits, change this to language-specific
+@c switches for what to include.
+@clear CONLY
+@c Discuss Fortran?
+@set FORTRAN
+@c
+@c Discuss Modula 2?
+@set MOD2
+@c
+@c Specifically for host machine running DOS?
+@clear DOSHOST
+@c
+@c Talk about CPU simulator targets?
+@set SIMS
+@c
+@c Is manual stand-alone, or part of an agglomeration, with overall GPL?
+@clear AGGLOMERATION
+@c
+@c Remote serial line settings of interest?
+@set SERIAL
+@c
+@c Discuss features requiring Posix or similar OS environment?
+@set POSIX
+@c
+@c Discuss remote serial debugging stub?
+@set REMOTESTUB
+@c
+@c Discuss gdbserver?
+@set GDBSERVER
+@c
+@c Refrain from discussing how to configure sw and format doc?
+@clear PRECONFIGURED
+@c
+@c Refrain from referring to unfree publications?
+@set FSFDOC
+@c
+@c ----------------------------------------------------------------------
+@c STRINGS:
+@c
+@c Name of GDB program. Used also for (gdb) prompt string.
+@set GDBP gdb
+@c
+@c Name of GDB product. Used in running text.
+@set GDBN GDB
+@c
+@c Name of GDB initialization file.
+@set GDBINIT .gdbinit
+@c
+@c Name of host. Should not be used in generic configs, but generic
+@c value may catch some flubs.
+@set HOST machine specific
+@c
+@c Name of GCC product
+@set NGCC GCC
+@c
+@c Name of GCC program
+@set GCC gcc
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.info b/gnu/usr.bin/gdb/doc/gdb.info
new file mode 100644
index 000000000000..c32646954b36
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info
@@ -0,0 +1,213 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+Indirect:
+gdb.info-1: 992
+gdb.info-2: 50863
+gdb.info-3: 98423
+gdb.info-4: 145674
+gdb.info-5: 194815
+gdb.info-6: 244253
+gdb.info-7: 290141
+gdb.info-8: 335234
+
+Tag Table:
+(Indirect)
+Node: Top992
+Node: Summary2561
+Node: Free Software3754
+Node: Contributors4492
+Node: New Features8199
+Node: Sample Session12215
+Node: Invocation19094
+Node: Invoking GDB19559
+Node: File Options21298
+Node: Mode Options24476
+Node: Quitting GDB26641
+Node: Shell Commands27359
+Node: Commands28106
+Node: Command Syntax28739
+Node: Completion30598
+Node: Help34666
+Node: Running38442
+Node: Compilation39426
+Node: Starting41224
+Node: Arguments44411
+Node: Environment45412
+Node: Working Directory48518
+Node: Input/Output49258
+Node: Attach50863
+Node: Kill Process53122
+Node: Process Information54097
+Node: Stopping55350
+Node: Breakpoints56423
+Node: Set Breaks58622
+Node: Set Watchpoints65221
+Node: Exception Handling66051
+Node: Delete Breaks68610
+Node: Disabling70238
+Node: Conditions72881
+Node: Break Commands77378
+Node: Breakpoint Menus80225
+Node: Error in Breakpoints81935
+Node: Continuing and Stepping82839
+Node: Signals89318
+Node: Stack92940
+Node: Frames94414
+Node: Backtrace96691
+Node: Selection98423
+Node: Frame Info100917
+Node: MIPS Stack102984
+Node: Source103857
+Node: List104806
+Node: Search108286
+Node: Source Path109085
+Node: Machine Code111763
+Node: Data114236
+Node: Expressions116111
+Node: Variables117793
+Node: Arrays120314
+Node: Output Formats122397
+Node: Memory124456
+Node: Auto Display128727
+Node: Print Settings132474
+Node: Value History140630
+Node: Convenience Vars143017
+Node: Registers145674
+Node: Floating Point Hardware150276
+Node: Languages150781
+Node: Setting151949
+Node: Manually152483
+Node: Automatically153663
+Node: Show154980
+Node: Checks155888
+Node: Type Checking157244
+Node: Range Checking159924
+Node: Support162265
+Node: C163185
+Node: C Operators164016
+Node: C Constants168071
+Node: Cplus expressions169974
+Node: C Defaults172597
+Node: C Checks173215
+Node: Debugging C173926
+Node: Debugging C plus plus174404
+Node: Modula-2176416
+Node: M2 Operators177308
+Node: Built-In Func/Proc180308
+Node: M2 Constants183051
+Node: M2 Defaults184640
+Node: Deviations185239
+Node: M2 Checks186330
+Node: M2 Scope187130
+Node: GDB/M2188142
+Node: Symbols189081
+Node: Altering194815
+Node: Assignment195797
+Node: Jumping197907
+Node: Signaling199914
+Node: Returning201034
+Node: Calling202226
+Node: Patching202700
+Node: GDB Files203782
+Node: Files204247
+Node: Symbol Errors214466
+Node: Targets218064
+Node: Active Targets218954
+Node: Target Commands220530
+Node: Remote223904
+Node: Remote Serial225315
+Node: Stub Contents227768
+Node: Bootstrapping229877
+Node: Debug Session233057
+Node: Protocol236218
+Node: Server239069
+Node: i960-Nindy Remote242748
+Node: Nindy Startup243568
+Node: Nindy Options244253
+Node: Nindy Reset245867
+Node: UDI29K Remote246251
+Node: EB29K Remote247172
+Node: Comms (EB29K)248006
+Node: gdb-EB29K251189
+Node: Remote Log252555
+Node: ST2000 Remote253030
+Node: VxWorks Remote254499
+Node: VxWorks Connection256224
+Node: VxWorks Download257150
+Node: VxWorks Attach258886
+Node: Hitachi Remote259281
+Node: MIPS Remote260790
+Node: Simulator262861
+Node: Controlling GDB264351
+Node: Prompt264962
+Node: Editing265571
+Node: History266338
+Node: Screen Size269024
+Node: Numbers270420
+Node: Messages/Warnings271538
+Node: Sequences274587
+Node: Define275147
+Node: Hooks277144
+Node: Command Files278547
+Node: Output280302
+Node: Emacs282714
+Node: GDB Bugs288669
+Node: Bug Criteria289387
+Node: Bug Reporting290141
+Node: Command Line Editing297342
+Node: Introduction and Notation297763
+Node: Readline Interaction298780
+Node: Readline Bare Essentials299914
+Node: Readline Movement Commands301417
+Node: Readline Killing Commands302303
+Node: Readline Arguments303941
+Node: Readline Init File304887
+Node: Readline Init Syntax305708
+Node: Commands For Moving309640
+Node: Commands For History310260
+Node: Commands For Text311330
+Node: Commands For Killing313046
+Node: Numeric Arguments314168
+Node: Commands For Completion314606
+Node: Miscellaneous Commands315325
+Node: Readline Vi Mode316077
+Node: Using History Interactively316784
+Node: History Interaction317141
+Node: Event Designators318189
+Node: Word Designators318828
+Node: Modifiers319724
+Node: Renamed Commands320469
+Node: Formatting Documentation322131
+Node: Installing GDB325465
+Node: Separate Objdir328945
+Node: Config Names331490
+Node: configure Options332918
+Node: Index335234
+
+End Tag Table
diff --git a/gnu/usr.bin/gdb/doc/gdb.info-1 b/gnu/usr.bin/gdb/doc/gdb.info-1
new file mode 100644
index 000000000000..a1d71201a5c8
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info-1
@@ -0,0 +1,1304 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+File: gdb.info, Node: Top, Next: Summary, Prev: (DIR), Up: (DIR)
+
+Debugging with GDB
+******************
+
+ This file describes GDB, the GNU symbolic debugger.
+
+ This is Edition 4.09, August 1993, for GDB Version 4.11.
+
+* Menu:
+
+* Summary:: Summary of GDB
+
+* New Features:: New features since GDB version 3.5
+
+* Sample Session:: A sample GDB session
+
+* Invocation:: Getting in and out of GDB
+* Commands:: GDB commands
+* Running:: Running programs under GDB
+* Stopping:: Stopping and continuing
+* Stack:: Examining the stack
+* Source:: Examining source files
+* Data:: Examining data
+
+* Languages:: Using GDB with different languages
+
+
+* Symbols:: Examining the symbol table
+* Altering:: Altering execution
+* GDB Files:: GDB files
+* Targets:: Specifying a debugging target
+* Controlling GDB:: Controlling GDB
+* Sequences:: Canned sequences of commands
+
+* Emacs:: Using GDB under GNU Emacs
+
+* GDB Bugs:: Reporting bugs in GDB
+* Command Line Editing:: Facilities of the readline library
+* Using History Interactively::
+
+* Renamed Commands::
+
+* Formatting Documentation:: How to format and print GDB documentation
+* Installing GDB:: Installing GDB
+
+* Index:: Index
+
+
+File: gdb.info, Node: Summary, Next: New Features, Prev: Top, Up: Top
+
+Summary of GDB
+**************
+
+ The purpose of a debugger such as GDB 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.
+
+ GDB can do four main kinds of things (plus other things in support of
+these) to help you catch bugs in the act:
+
+ * Start your program, specifying anything that might affect its
+ behavior.
+
+ * Make your program stop on specified conditions.
+
+ * Examine what has happened, when your program has stopped.
+
+ * Change things in your program, so you can experiment with
+ correcting the effects of one bug and go on to learn about another.
+
+ You can use GDB to debug programs written in C, C++, and Modula-2.
+G{No Value For "DBN"} can be used to debug programs written in Fortran,
+although it does not yet support entering expressions, printing values,
+etc. using Fortran syntax. It may be necessary to refer to some
+variables with a trailing underscore.
+
+* Menu:
+
+* Free Software:: Freely redistributable software
+* Contributors:: Contributors to GDB
+
+
+File: gdb.info, Node: Free Software, Next: Contributors, Up: Summary
+
+Free software
+=============
+
+ GDB 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 cannot take these freedoms
+away from anyone else.
+
+
+File: gdb.info, Node: Contributors, Prev: Free Software, Up: Summary
+
+Contributors to GDB
+===================
+
+ Richard Stallman was the original author of GDB, and of many other
+GNU programs. Many others have contributed to its development. This
+section attempts to credit major contributors. One of the virtues of
+free software is that everyone is free to contribute to it; with
+regret, we cannot actually acknowledge everyone here. The file
+`ChangeLog' in the GDB distribution approximates a blow-by-blow account.
+
+ Changes much prior to version 2.0 are lost in the mists of time.
+
+ *Plea:* Additions to this section are particularly welcome. If you
+ or your friends (or enemies, to be evenhanded) have been unfairly
+ omitted from this list, we would like to add your names!
+
+ So that they may not regard their long labor as thankless, we
+particularly thank those who shepherded GDB through major releases: Fred
+Fish (releases 4.11, 4.10, 4.9), Stu Grossman and John Gilmore (releases
+4.8, 4.7, 4.6, 4.5, 4.4), John Gilmore (releases 4.3, 4.2, 4.1, 4.0, and
+3.9); Jim Kingdon (releases 3.5, 3.4, 3.3); and Randy Smith (releases
+3.2, 3.1, 3.0). As major maintainer of GDB for some period, each
+contributed significantly to the structure, stability, and capabilities
+of the entire debugger.
+
+ Richard Stallman, assisted at various times by Peter TerMaat, Chris
+Hanson, and Richard Mlynarik, handled releases through 2.8.
+
+ Michael Tiemann is the author of most of the GNU C++ support in GDB,
+with significant additional contributions from Per Bothner. James
+Clark wrote the GNU C++ demangler. Early work on C++ was by Peter
+TerMaat (who also did much general update work leading to release 3.0).
+
+ GDB 4 uses the BFD subroutine library to examine multiple
+object-file formats; BFD was a joint project of David V.
+Henkel-Wallace, Rich Pixley, Steve Chamberlain, and John Gilmore.
+
+ David Johnson wrote the original COFF support; Pace Willison did the
+original support for encapsulated COFF.
+
+ Adam de Boor and Bradley Davis contributed the ISI Optimum V support.
+Per Bothner, Noboyuki Hikichi, and Alessandro Forin contributed MIPS
+support. Jean-Daniel Fekete contributed Sun 386i support. Chris
+Hanson improved the HP9000 support. Noboyuki Hikichi and Tomoyuki
+Hasei contributed Sony/News OS 3 support. David Johnson contributed
+Encore Umax support. Jyrki Kuoppala contributed Altos 3068 support.
+Keith Packard contributed NS32K support. Doug Rabson contributed Acorn
+Risc Machine support. Chris Smith contributed Convex support (and
+Fortran debugging). Jonathan Stone contributed Pyramid support.
+Michael Tiemann contributed SPARC support. Tim Tucker contributed
+support for the Gould NP1 and Gould Powernode. Pace Willison
+contributed Intel 386 support. Jay Vosburgh contributed Symmetry
+support.
+
+ Rich Schaefer and Peter Schauer helped with support of SunOS shared
+libraries.
+
+ Jay Fenlason and Roland McGrath ensured that GDB and GAS agree about
+several machine instruction sets.
+
+ Patrick Duval, Ted Goldstein, Vikram Koka and Glenn Engel helped
+develop remote debugging. Intel Corporation and Wind River Systems
+contributed remote debugging modules for their products.
+
+ Brian Fox is the author of the readline libraries providing
+command-line editing and command history.
+
+ Andrew Beers of SUNY Buffalo wrote the language-switching code, the
+Modula-2 support, and contributed the Languages chapter of this manual.
+
+ Fred Fish wrote most of the support for Unix System Vr4. He also
+enhanced the command-completion support to cover C++ overloaded symbols.
+
+ Hitachi America, Ltd. sponsored the support for Hitachi
+microprocessors.
+
+
+File: gdb.info, Node: New Features, Next: Sample Session, Prev: Summary, Up: Top
+
+New Features since GDB Version 3.5
+**********************************
+
+*Targets*
+ Using the new command `target', you can select at runtime whether
+ you are debugging local files, local processes, standalone systems
+ over a serial port, realtime systems over a TCP/IP connection,
+ etc. The command `load' can download programs into a remote
+ system. Serial stubs are available for Motorola 680x0, Intel
+ 80386, and Sparc remote systems; GDB also supports debugging
+ realtime processes running under VxWorks, using SunRPC Remote
+ Procedure Calls over TCP/IP to talk to a debugger stub on the
+ target system. Internally, GDB now uses a function vector to
+ mediate access to different targets; if you need to add your own
+ support for a remote protocol, this makes it much easier.
+
+*Watchpoints*
+ GDB 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 your
+ program where this may happen.
+
+*Wide Output*
+ Commands that issue wide output now insert newlines at places
+ designed to make the output more readable.
+
+*Object Code Formats*
+ GDB uses a new library called the Binary File Descriptor (BFD)
+ Library to permit it to switch dynamically, without
+ reconfiguration or recompilation, between different object-file
+ formats. Formats currently supported are COFF, ELF, a.out, Intel
+ 960 b.out, MIPS ECOFF, HPPA SOM (with stabs debugging), and
+ S-records; files may be read as .o files, 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.
+
+*Configuration and Ports*
+ Compile-time configuration (to select a particular architecture and
+ operating system) is much easier. The script `configure' now
+ allows you to configure GDB as either a native debugger or a
+ cross-debugger. *Note Installing GDB::, for details on how to
+ configure.
+
+*Interaction*
+ The user interface to the GDB control variables is simpler, and is
+ consolidated in two commands, `set' and `show'. Output lines are
+ now broken at readable places, rather than overflowing onto the
+ next line. You can suppress output of machine-level addresses,
+ displaying only source language information.
+
+*C++*
+ GDB now supports C++ multiple inheritance (if used with a GCC
+ version 2 compiler), and also has limited support for C++ exception
+ handling, with the commands `catch' and `info catch': GDB can
+ break when an exception is raised, before the stack is peeled back
+ to the exception handler's context.
+
+*Modula-2*
+ GDB now has preliminary support for the GNU Modula-2 compiler,
+ currently under development at the State University of New York at
+ Buffalo. Coordinated development of both GDB and the GNU Modula-2
+ compiler will continue. Other Modula-2 compilers are currently
+ not supported, and attempting to debug programs compiled with them
+ will likely result in an error as the symbol table of the
+ executable is read in.
+
+*Command Rationalization*
+ Many GDB commands have been renamed to make them easier to remember
+ and use. In particular, the subcommands of `info' and
+ `show'/`set' are grouped to make the former refer to the state of
+ your program, and the latter refer to the state of GDB itself.
+ *Note Renamed Commands::, for details on what commands were
+ renamed.
+
+*Shared Libraries*
+ GDB 4 can debug programs and core files that use SunOS, SVR4, or
+ IBM RS/6000 shared libraries.
+
+*Reference Card*
+ GDB 4 has a reference card. *Note Formatting the Documentation:
+ Formatting Documentation, for instructions about how to print it.
+
+
+File: gdb.info, Node: Sample Session, Next: Invocation, Prev: New Features, Up: Top
+
+A Sample GDB Session
+********************
+
+ You can use this manual at your leisure to read all about GDB.
+However, a handful of commands are enough to get started using the
+debugger. This chapter illustrates those commands.
+
+ One of the preliminary versions of GNU `m4' (a generic macro
+processor) exhibits the following bug: sometimes, when we change its
+quote strings from the default, the commands used to capture one macro
+definition within another stop working. In the following short `m4'
+session, we define a macro `foo' which expands to `0000'; we then use
+the `m4' built-in `defn' to define `bar' as the same thing. However,
+when we change the open quote string to `<QUOTE>' and the close quote
+string to `<UNQUOTE>', the same procedure fails to define a new synonym
+`baz':
+
+ $ cd gnu/m4
+ $ ./m4
+ define(foo,0000)
+
+ foo
+ 0000
+ define(bar,defn(`foo'))
+
+ bar
+ 0000
+ changequote(<QUOTE>,<UNQUOTE>)
+
+ define(baz,defn(<QUOTE>foo<UNQUOTE>))
+ baz
+ C-d
+ m4: End of input: 0: fatal error: EOF in string
+
+Let us use GDB to try to see what is going on.
+
+ $ gdb m4
+ GDB is free software and you are welcome to distribute copies
+ of it under certain conditions; type "show copying" to see
+ the conditions.
+ There is absolutely no warranty for GDB; type "show warranty"
+ for details.
+ GDB 4.11, Copyright 1993 Free Software Foundation, Inc...
+ (gdb)
+
+GDB reads only enough symbol data to know where to find the rest when
+needed; as a result, the first prompt comes up very quickly. We now
+tell GDB to use a narrower display width than usual, so that examples
+will fit in this manual.
+
+ (gdb) set width 70
+
+We need to see how the `m4' built-in `changequote' works. Having
+looked at the source, we know the relevant subroutine is
+`m4_changequote', so we set a breakpoint there with the GDB `break'
+command.
+
+ (gdb) break m4_changequote
+ Breakpoint 1 at 0x62f4: file builtin.c, line 879.
+
+Using the `run' command, we start `m4' running under GDB control; as
+long as control does not reach the `m4_changequote' subroutine, the
+program runs as usual:
+
+ (gdb) run
+ Starting program: /work/Editorial/gdb/gnu/m4/m4
+ define(foo,0000)
+
+ foo
+ 0000
+
+To trigger the breakpoint, we call `changequote'. GDB suspends
+execution of `m4', displaying information about the context where it
+stops.
+
+ changequote(<QUOTE>,<UNQUOTE>)
+
+ Breakpoint 1, m4_changequote (argc=3, argv=0x33c70)
+ at builtin.c:879
+ 879 if (bad_argc(TOKEN_DATA_TEXT(argv[0]),argc,1,3))
+
+Now we use the command `n' (`next') to advance execution to the next
+line of the current function.
+
+ (gdb) n
+ 882 set_quotes((argc >= 2) ? TOKEN_DATA_TEXT(argv[1])\
+ : nil,
+
+`set_quotes' looks like a promising subroutine. We can go into it by
+using the command `s' (`step') instead of `next'. `step' goes to the
+next line to be executed in *any* subroutine, so it steps into
+`set_quotes'.
+
+ (gdb) s
+ set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
+ at input.c:530
+ 530 if (lquote != def_lquote)
+
+The display that shows the subroutine where `m4' is now suspended (and
+its arguments) is called a stack frame display. It shows a summary of
+the stack. We can use the `backtrace' command (which can also be
+spelled `bt'), to see where we are in the stack as a whole: the
+`backtrace' command displays a stack frame for each active subroutine.
+
+ (gdb) bt
+ #0 set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
+ at input.c:530
+ #1 0x6344 in m4_changequote (argc=3, argv=0x33c70)
+ at builtin.c:882
+ #2 0x8174 in expand_macro (sym=0x33320) at macro.c:242
+ #3 0x7a88 in expand_token (obs=0x0, t=209696, td=0xf7fffa30)
+ at macro.c:71
+ #4 0x79dc in expand_input () at macro.c:40
+ #5 0x2930 in main (argc=0, argv=0xf7fffb20) at m4.c:195
+
+We will step through a few more lines to see what happens. The first
+two times, we can use `s'; the next two times we use `n' to avoid
+falling into the `xstrdup' subroutine.
+
+ (gdb) s
+ 0x3b5c 532 if (rquote != def_rquote)
+ (gdb) s
+ 0x3b80 535 lquote = (lq == nil || *lq == '\0') ? \
+ def_lquote : xstrdup(lq);
+ (gdb) n
+ 536 rquote = (rq == nil || *rq == '\0') ? def_rquote\
+ : xstrdup(rq);
+ (gdb) n
+ 538 len_lquote = strlen(rquote);
+
+The last line displayed looks a little odd; we can examine the variables
+`lquote' and `rquote' to see if they are in fact the new left and right
+quotes we specified. We use the command `p' (`print') to see their
+values.
+
+ (gdb) p lquote
+ $1 = 0x35d40 "<QUOTE>"
+ (gdb) p rquote
+ $2 = 0x35d50 "<UNQUOTE>"
+
+`lquote' and `rquote' are indeed the new left and right quotes. To
+look at some context, we can display ten lines of source surrounding
+the current line with the `l' (`list') command.
+
+ (gdb) l
+ 533 xfree(rquote);
+ 534
+ 535 lquote = (lq == nil || *lq == '\0') ? def_lquote\
+ : xstrdup (lq);
+ 536 rquote = (rq == nil || *rq == '\0') ? def_rquote\
+ : xstrdup (rq);
+ 537
+ 538 len_lquote = strlen(rquote);
+ 539 len_rquote = strlen(lquote);
+ 540 }
+ 541
+ 542 void
+
+Let us step past the two lines that set `len_lquote' and `len_rquote',
+and then examine the values of those variables.
+
+ (gdb) n
+ 539 len_rquote = strlen(lquote);
+ (gdb) n
+ 540 }
+ (gdb) p len_lquote
+ $3 = 9
+ (gdb) p len_rquote
+ $4 = 7
+
+That certainly looks wrong, assuming `len_lquote' and `len_rquote' are
+meant to be the lengths of `lquote' and `rquote' respectively. We can
+set them to better values using the `p' command, since it can print the
+value of any expression--and that expression can include subroutine
+calls and assignments.
+
+ (gdb) p len_lquote=strlen(lquote)
+ $5 = 7
+ (gdb) p len_rquote=strlen(rquote)
+ $6 = 9
+
+Is that enough to fix the problem of using the new quotes with the `m4'
+built-in `defn'? We can allow `m4' to continue executing with the `c'
+(`continue') command, and then try the example that caused trouble
+initially:
+
+ (gdb) c
+ Continuing.
+
+ define(baz,defn(<QUOTE>foo<UNQUOTE>))
+
+ baz
+ 0000
+
+Success! The new quotes now work just as well as the default ones. The
+problem seems to have been just the two typos defining the wrong
+lengths. We allow `m4' exit by giving it an EOF as input:
+
+ C-d
+ Program exited normally.
+
+The message `Program exited normally.' is from GDB; it indicates `m4'
+has finished executing. We can end our GDB session with the GDB `quit'
+command.
+
+ (gdb) quit
+
+
+File: gdb.info, Node: Invocation, Next: Commands, Prev: Sample Session, Up: Top
+
+Getting In and Out of GDB
+*************************
+
+ This chapter discusses how to start GDB, and how to get out of it.
+(The essentials: type `gdb' to start GDB, and type `quit' or `C-d' to
+exit.)
+
+* Menu:
+
+* Invoking GDB:: How to start GDB
+* Quitting GDB:: How to quit GDB
+* Shell Commands:: How to use shell commands inside GDB
+
+
+File: gdb.info, Node: Invoking GDB, Next: Quitting GDB, Up: Invocation
+
+Invoking GDB
+============
+
+ Invoke GDB by running the program `gdb'. Once started, GDB reads
+commands from the terminal until you tell it to exit.
+
+ You can also run `gdb' with a variety of arguments and options, to
+specify more of your debugging environment at the outset.
+
+ The command-line options described here are designed to cover a
+variety of situations; in some environments, some of these options may
+effectively be unavailable.
+
+ The most usual way to start GDB is with one argument, specifying an
+executable program:
+
+ gdb PROGRAM
+
+You can also start with both an executable program and a core file
+specified:
+
+ gdb PROGRAM CORE
+
+ You can, instead, specify a process ID as a second argument, if you
+want to debug a running process:
+
+ gdb PROGRAM 1234
+
+would attach GDB to process `1234' (unless you also have a file named
+`1234'; GDB does check for a core file first).
+
+ Taking advantage of the second command-line argument requires a
+fairly complete operating system; when you use GDB as a remote debugger
+attached to a bare board, there may not be any notion of "process", and
+there is often no way to get a core dump.
+
+You can further control how GDB starts up by using command-line
+options. GDB itself can remind you of the options available.
+
+Type
+
+ gdb -help
+
+to display all available options and briefly describe their use (`gdb
+-h' is a shorter equivalent).
+
+ All options and command line arguments you give are processed in
+sequential order. The order makes a difference when the `-x' option is
+used.
+
+* Menu:
+
+
+
+* File Options:: Choosing files
+* Mode Options:: Choosing modes
+
+
+File: gdb.info, Node: File Options, Next: Mode Options, Up: Invoking GDB
+
+Choosing files
+--------------
+
+ When GDB starts, it reads any arguments other than options as
+specifying an executable file and core file (or process ID). This is
+the same as if the arguments were specified by the `-se' and `-c'
+options respectively. (GDB reads the first argument that does not have
+an associated option flag as equivalent to the `-se' option followed by
+that argument; and the second argument that does not have an associated
+option flag, if any, as equivalent to the `-c' option followed by that
+argument.)
+
+ Many options have both long and short forms; both are shown in the
+following list. GDB also recognizes the long forms if you truncate
+them, so long as enough of the option is present to be unambiguous.
+(If you prefer, you can flag option arguments with `--' rather than
+`-', though we illustrate the more usual convention.)
+
+`-symbols FILE'
+`-s FILE'
+ Read symbol table from file FILE.
+
+`-exec FILE'
+`-e FILE'
+ Use file FILE as the executable file to execute when appropriate,
+ and for examining pure data in conjunction with a core dump.
+
+`-se FILE'
+ Read symbol table from file FILE and use it as the executable file.
+
+`-core FILE'
+`-c FILE'
+ Use file FILE as a core dump to examine.
+
+`-c NUMBER'
+ Connect to process ID NUMBER, as with the `attach' command (unless
+ there is a file in core-dump format named NUMBER, in which case
+ `-c' specifies that file as a core dump to read).
+
+`-command FILE'
+`-x FILE'
+ Execute GDB commands from file FILE. *Note Command files: Command
+ Files.
+
+`-directory DIRECTORY'
+`-d DIRECTORY'
+ Add DIRECTORY to the path to search for source files.
+
+`-m'
+`-mapped'
+ *Warning: this option depends on operating system facilities that
+ are not supported on all systems.*
+ If memory-mapped files are available on your system through the
+ `mmap' system call, you can use this option to have GDB write the
+ symbols from your program into a reusable file in the current
+ directory. If the program you are debugging is called
+ `/tmp/fred', the mapped symbol file will be `./fred.syms'. Future
+ GDB debugging sessions will notice the presence of this file, and
+ will quickly map in symbol information from it, rather than reading
+ the symbol table from the executable program.
+
+ The `.syms' file is specific to the host machine where GDB is run.
+ It holds an exact image of the internal GDB symbol table. It
+ cannot be shared across multiple host platforms.
+
+`-r'
+`-readnow'
+ Read each symbol file's entire symbol table immediately, rather
+ than the default, which is to read it incrementally as it is
+ needed. This makes startup slower, but makes future operations
+ faster.
+
+ The `-mapped' and `-readnow' options are typically combined in order
+to build a `.syms' file that contains complete symbol information.
+(*Note Commands to specify files: Files, for information on `.syms'
+files.) A simple GDB invocation to do nothing but build a `.syms' file
+for future use is:
+
+ gdb -batch -nx -mapped -readnow programname
+
+
+File: gdb.info, Node: Mode Options, Prev: File Options, Up: Invoking GDB
+
+Choosing modes
+--------------
+
+ You can run GDB in various alternative modes--for example, in batch
+mode or quiet mode.
+
+`-nx'
+`-n'
+ Do not execute commands from any initialization files (normally
+ called `.gdbinit'). Normally, the commands in these files are
+ executed after all the command options and arguments have been
+ processed. *Note Command files: Command Files.
+
+`-quiet'
+`-q'
+ "Quiet". Do not print the introductory and copyright messages.
+ These messages are also suppressed in batch mode.
+
+`-batch'
+ Run in batch mode. Exit with status `0' after processing all the
+ command files specified with `-x' (and all commands from
+ initialization files, if not inhibited with `-n'). Exit with
+ nonzero status if an error occurs in executing the GDB commands in
+ the command files.
+
+ Batch mode may be useful for running GDB as a filter, for example
+ to download and run a program on another computer; in order to
+ make this more useful, the message
+
+ Program exited normally.
+
+ (which is ordinarily issued whenever a program running under GDB
+ control terminates) is not issued when running in batch mode.
+
+`-cd DIRECTORY'
+ Run GDB using DIRECTORY as its working directory, instead of the
+ current directory.
+
+`-fullname'
+`-f'
+ Emacs sets this option when it runs GDB as a subprocess. It tells
+ GDB 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 your program stops). This recognizable format
+ looks like two `\032' characters, followed by the file name, line
+ number and character position separated by colons, and a newline.
+ The Emacs-to-GDB interface program uses the two `\032' characters
+ as a signal to display the source code for the frame.
+
+`-b BPS'
+ Set the line speed (baud rate or bits per second) of any serial
+ interface used by GDB for remote debugging.
+
+`-tty DEVICE'
+ Run using DEVICE for your program's standard input and output.
+
+
+File: gdb.info, Node: Quitting GDB, Next: Shell Commands, Prev: Invoking GDB, Up: Invocation
+
+Quitting GDB
+============
+
+`quit'
+ To exit GDB, use the `quit' command (abbreviated `q'), or type an
+ end-of-file character (usually `C-d').
+
+ An interrupt (often `C-c') will not exit from GDB, but rather will
+terminate the action of any GDB command that is in progress and return
+to GDB command level. It is safe to type the interrupt character at
+any time because GDB does not allow it to take effect until a time when
+it is safe.
+
+ If you have been using GDB to control an attached process or device,
+you can release it with the `detach' command (*note Debugging an
+already-running process: Attach.).
+
+
+File: gdb.info, Node: Shell Commands, Prev: Quitting GDB, Up: Invocation
+
+Shell commands
+==============
+
+ If you need to execute occasional shell commands during your
+debugging session, there is no need to leave or suspend GDB; you can
+just use the `shell' command.
+
+`shell COMMAND STRING'
+ Invoke a the standard shell to execute COMMAND STRING. If it
+ exists, the environment variable `SHELL' determines which shell to
+ run. Otherwise GDB uses `/bin/sh'.
+
+ The utility `make' is often needed in development environments. You
+do not have to use the `shell' command for this purpose in GDB:
+
+`make MAKE-ARGS'
+ Execute the `make' program with the specified arguments. This is
+ equivalent to `shell make MAKE-ARGS'.
+
+
+File: gdb.info, Node: Commands, Next: Running, Prev: Invocation, Up: Top
+
+GDB Commands
+************
+
+ You can abbreviate a GDB command to the first few letters of the
+command name, if that abbreviation is unambiguous; and you can repeat
+certain GDB commands by typing just RET. You can also use the TAB key
+to get GDB to fill out the rest of a word in a command (or to show you
+the alternatives available, if there is more than one possibility).
+
+* Menu:
+
+* Command Syntax:: How to give commands to GDB
+* Completion:: Command completion
+* Help:: How to ask GDB for help
+
+
+File: gdb.info, Node: Command Syntax, Next: Completion, Up: Commands
+
+Command syntax
+==============
+
+ A GDB 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 `step' accepts an argument which is the number of times to
+step, as in `step 5'. You can also use the `step' command with no
+arguments. Some command names do not allow any arguments.
+
+ GDB command names may always be truncated if that abbreviation is
+unambiguous. Other possible command abbreviations are listed in the
+documentation for individual commands. In some cases, even ambiguous
+abbreviations are allowed; for example, `s' is specially defined as
+equivalent to `step' even though there are other commands whose names
+start with `s'. You can test abbreviations by using them as arguments
+to the `help' command.
+
+ A blank line as input to GDB (typing just RET) means to repeat the
+previous command. Certain commands (for example, `run') will not repeat
+this way; these are commands for which unintentional repetition might
+cause trouble and which you are unlikely to want to repeat.
+
+ The `list' and `x' commands, when you repeat them with RET,
+construct new arguments rather than repeating exactly as typed. This
+permits easy scanning of source or memory.
+
+ GDB can also use RET in another way: to partition lengthy output, in
+a way similar to the common utility `more' (*note Screen size: Screen
+Size.). Since it is easy to press one RET too many in this situation,
+GDB disables command repetition after any command that generates this
+sort of display.
+
+ Any text from a `#' to the end of the line is a comment; it does
+nothing. This is useful mainly in command files (*note Command files:
+Command Files.).
+
+
+File: gdb.info, Node: Completion, Next: Help, Prev: Command Syntax, Up: Commands
+
+Command completion
+==================
+
+ GDB can fill in the rest of a word in a command for you, if there is
+only one possibility; it can also show you what the valid possibilities
+are for the next word in a command, at any time. This works for GDB
+commands, GDB subcommands, and the names of symbols in your program.
+
+ Press the TAB key whenever you want GDB to fill out the rest of a
+word. If there is only one possibility, GDB will fill in the word, and
+wait for you to finish the command (or press RET to enter it). For
+example, if you type
+
+ (gdb) info bre TAB
+
+GDB fills in the rest of the word `breakpoints', since that is the only
+`info' subcommand beginning with `bre':
+
+ (gdb) info breakpoints
+
+You can either press RET at this point, to run the `info breakpoints'
+command, or backspace and enter something else, if `breakpoints' does
+not look like the command you expected. (If you were sure you wanted
+`info breakpoints' in the first place, you might as well just type RET
+immediately after `info bre', to exploit command abbreviations rather
+than command completion).
+
+ If there is more than one possibility for the next word when you
+press TAB, GDB will sound a bell. You can either supply more
+characters and try again, or just press TAB a second time, and GDB will
+display all the possible completions for that word. For example, you
+might want to set a breakpoint on a subroutine whose name begins with
+`make_', but when you type `b make_TAB' GDB just sounds the bell.
+Typing TAB again will display all the function names in your program
+that begin with those characters, for example:
+
+ (gdb) b make_ TAB
+GDB sounds bell; press TAB again, to see:
+ make_a_section_from_file make_environ
+ make_abs_section make_function_type
+ make_blockvector make_pointer_type
+ make_cleanup make_reference_type
+ make_command make_symbol_completion_list
+ (gdb) b make_
+
+After displaying the available possibilities, GDB copies your partial
+input (`b make_' in the example) so you can finish the command.
+
+ If you just want to see the list of alternatives in the first place,
+you can press `M-?' rather than pressing TAB twice. `M-?' means `META
+?'. You can type this either by holding down a key designated as the
+META shift on your keyboard (if there is one) while typing `?', or as
+ESC followed by `?'.
+
+ Sometimes the string you need, while logically a "word", may contain
+parentheses or other characters that GDB normally excludes from its
+notion of a word. To permit word completion to work in this situation,
+you may enclose words in `'' (single quote marks) in GDB commands.
+
+ The most likely situation where you might need this is in typing the
+name of a C++ function. This is because C++ allows function overloading
+(multiple definitions of the same function, distinguished by argument
+type). For example, when you want to set a breakpoint you may need to
+distinguish whether you mean the version of `name' that takes an `int'
+parameter, `name(int)', or the version that takes a `float' parameter,
+`name(float)'. To use the word-completion facilities in this
+situation, type a single quote `'' at the beginning of the function
+name. This alerts GDB that it may need to consider more information
+than usual when you press TAB or `M-?' to request word completion:
+
+ (gdb) b 'bubble( M-?
+ bubble(double,double) bubble(int,int)
+ (gdb) b 'bubble(
+
+ In some cases, GDB can tell that completing a name will require
+quotes. When this happens, GDB will insert the quote for you (while
+completing as much as it can) if you do not type the quote in the first
+place:
+
+ (gdb) b bub TAB
+GDB alters your input line to the following, and rings a bell:
+ (gdb) b 'bubble(
+
+In general, GDB can tell that a quote is needed (and inserts it) if you
+have not yet started typing the argument list when you ask for
+completion on an overloaded symbol.
+
+
+File: gdb.info, Node: Help, Prev: Completion, Up: Commands
+
+Getting help
+============
+
+ You can always ask GDB itself for information on its commands, using
+the command `help'.
+
+`help'
+`h'
+ You can use `help' (abbreviated `h') with no arguments to display
+ a short list of named classes of commands:
+
+ (gdb) 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.
+ (gdb)
+
+`help CLASS'
+ Using one of the general help classes as an argument, you can get a
+ list of the individual commands in that class. For example, here
+ is the help display for the class `status':
+
+ (gdb) 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.
+ (gdb)
+
+`help COMMAND'
+ With a command name as `help' argument, GDB will display a short
+ paragraph on how to use that command.
+
+ In addition to `help', you can use the GDB commands `info' and
+`show' to inquire about the state of your program, or the state of GDB
+itself. Each command supports many topics of inquiry; this manual
+introduces each of them in the appropriate context. The listings under
+`info' and under `show' in the Index point to all the sub-commands.
+*Note Index::.
+
+`info'
+ This command (abbreviated `i') is for describing the state of your
+ program. For example, you can list the arguments given to your
+ program with `info args', list the registers currently in use with
+ `info registers', or list the breakpoints you have set with `info
+ breakpoints'. You can get a complete list of the `info'
+ sub-commands with `help info'.
+
+`show'
+ In contrast, `show' is for describing the state of GDB itself.
+ You can change most of the things you can `show', by using the
+ related command `set'; for example, you can control what number
+ system is used for displays with `set radix', or simply inquire
+ which is currently in use with `show radix'.
+
+ To display all the settable parameters and their current values,
+ you can use `show' with no arguments; you may also use `info set'.
+ Both commands produce the same display.
+
+ Here are three miscellaneous `show' subcommands, all of which are
+exceptional in lacking corresponding `set' commands:
+
+`show version'
+ Show what version of GDB is running. You should include this
+ information in GDB bug-reports. If multiple versions of GDB are in
+ use at your site, you may occasionally want to determine which
+ version of GDB you are running; as GDB evolves, new commands are
+ introduced, and old ones may wither away. The version number is
+ also announced when you start GDB.
+
+`show copying'
+ Display information about permission for copying GDB.
+
+`show warranty'
+ Display the GNU "NO WARRANTY" statement.
+
+
+File: gdb.info, Node: Running, Next: Stopping, Prev: Commands, Up: Top
+
+Running Programs Under GDB
+**************************
+
+ When you run a program under GDB, you must first generate debugging
+information when you compile it. You may start it with its arguments,
+if any, in an environment of your choice. You may redirect your
+program's input and output, debug an already running process, or kill a
+child process.
+
+* Menu:
+
+* Compilation:: Compiling for debugging
+* Starting:: Starting your program
+
+* Arguments:: Your program's arguments
+* Environment:: Your program's environment
+* Working Directory:: Your program's working directory
+* Input/Output:: Your program's input and output
+* Attach:: Debugging an already-running process
+* Kill Process:: Killing the child process
+* Process Information:: Additional process information
+
+
+File: gdb.info, Node: Compilation, Next: Starting, Up: Running
+
+Compiling for debugging
+=======================
+
+ In order to debug a program effectively, you need to generate
+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 `-g' option when you
+run the compiler.
+
+ Many C compilers are unable to handle the `-g' and `-O' options
+together. Using those compilers, you cannot generate optimized
+executables containing debugging information.
+
+ GCC, the GNU C compiler, supports `-g' with or without `-O', making
+it possible to debug optimized code. We recommend that you *always*
+use `-g' whenever you compile a program. You may think your program is
+correct, but there is no sense in pushing your luck.
+
+ When you debug a program compiled with `-g -O', remember that the
+optimizer is rearranging your code; the debugger will show you what is
+really there. Do not be too surprised when the execution path does not
+exactly match your source file! An extreme example: if you define a
+variable, but never use it, GDB will never see that variable--because
+the compiler optimizes it out of existence.
+
+ Some things do not work as well with `-g -O' as with just `-g',
+particularly on machines with instruction scheduling. If in doubt,
+recompile with `-g' alone, and if this fixes the problem, please report
+it as a bug (including a test case!).
+
+ Older versions of the GNU C compiler permitted a variant option
+`-gg' for debugging information. GDB no longer supports this format;
+if your GNU C compiler has this option, do not use it.
+
+
+File: gdb.info, Node: Starting, Next: Arguments, Prev: Compilation, Up: Running
+
+Starting your program
+=====================
+
+`run'
+`r'
+ Use the `run' command to start your program under GDB. You must
+ first specify the program name (except on VxWorks) with an
+ argument to GDB (*note Getting In and Out of GDB: Invocation.), or
+ by using the `file' or `exec-file' command (*note Commands to
+ specify files: Files.).
+
+ If you are running your program in an execution environment that
+supports processes, `run' creates an inferior process and makes that
+process run your program. (In environments without processes, `run'
+jumps to the start of your program.)
+
+ The execution of a program is affected by certain information it
+receives from its superior. GDB provides ways to specify this
+information, which you must do *before* starting your program. (You
+can change it after starting your program, but such changes will only
+affect your program the next time you start it.) This information may
+be divided into four categories:
+
+The *arguments.*
+ Specify the arguments to give your program as the arguments of the
+ `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 (such as wildcard expansion or variable substitution)
+ in describing the arguments. In Unix systems, you can control
+ which shell is used with the `SHELL' environment variable. *Note
+ Your program's arguments: Arguments.
+
+The *environment.*
+ Your program normally inherits its environment from GDB, but you
+ can use the GDB commands `set environment' and `unset environment'
+ to change parts of the environment that will be given to your
+ program. *Note Your program's environment: Environment.
+
+The *working directory.*
+ Your program inherits its working directory from GDB. You can set
+ the GDB working directory with the `cd' command in GDB. *Note
+ Your program's working directory: Working Directory.
+
+The *standard input and output.*
+ Your program normally uses the same device for standard input and
+ standard output as GDB is using. You can redirect input and output
+ in the `run' command line, or you can use the `tty' command to set
+ a different device for your program. *Note Your program's input
+ and output: Input/Output.
+
+ *Warning:* While input and output redirection work, you cannot use
+ pipes to pass the output of the program you are debugging to
+ another program; if you attempt this, GDB is likely to wind up
+ debugging the wrong program.
+
+ When you issue the `run' command, your program begins to execute
+immediately. *Note Stopping and continuing: Stopping, for discussion
+of how to arrange for your program to stop. Once your program has
+stopped, you may call functions in your program, using the `print' or
+`call' commands. *Note Examining Data: Data.
+
+ If the modification time of your symbol file has changed since the
+last time GDB read its symbols, GDB will discard its symbol table and
+re-read it. When it does this, GDB tries to retain your current
+breakpoints.
+
+
+File: gdb.info, Node: Arguments, Next: Environment, Prev: Starting, Up: Running
+
+Your program's arguments
+========================
+
+ The arguments to your program can be specified by the arguments of
+the `run' command. They are passed to a shell, which expands wildcard
+characters and performs redirection of I/O, and thence to your program.
+Your `SHELL' environment variable (if it exists) specifies what shell
+GDB if you do not define `SHELL', GDB uses `/bin/sh'.
+
+ `run' with no arguments uses the same arguments used by the previous
+`run', or those set by the `set args' command.
+
+`set args'
+ Specify the arguments to be used the next time your program is
+ run. If `set args' has no arguments, `run' will execute your
+ program with no arguments. Once you have run your program with
+ arguments, using `set args' before the next `run' is the only way
+ to run it again without arguments.
+
+`show args'
+ Show the arguments to give your program when it is started.
+
+
+File: gdb.info, Node: Environment, Next: Working Directory, Prev: Arguments, Up: Running
+
+Your program's environment
+==========================
+
+ The "environment" consists of a set of 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 your
+program with a modified environment without having to start GDB over
+again.
+
+`path DIRECTORY'
+ Add DIRECTORY to the front of the `PATH' environment variable (the
+ search path for executables), for both GDB and your program. You
+ may specify several directory names, separated by `:' or
+ whitespace. If DIRECTORY is already in the path, it is moved to
+ the front, so it will be searched sooner.
+
+ You can use the string `$cwd' to refer to whatever is the current
+ working directory at the time GDB searches the path. If you use
+ `.' instead, it refers to the directory where you executed the
+ `path' command. GDB replaces `.' in the DIRECTORY argument (with
+ the current path) before adding DIRECTORY to the search path.
+
+`show paths'
+ Display the list of search paths for executables (the `PATH'
+ environment variable).
+
+`show environment [VARNAME]'
+ Print the value of environment variable VARNAME to be given to
+ your program when it starts. If you do not supply VARNAME, print
+ the names and values of all environment variables to be given to
+ your program. You can abbreviate `environment' as `env'.
+
+`set environment VARNAME [=] VALUE'
+ Set environment variable VARNAME to VALUE. The value changes for
+ your program only, not for GDB itself. VALUE may be any string;
+ the values of environment variables are just strings, and any
+ interpretation is supplied by your program itself. The VALUE
+ parameter is optional; if it is eliminated, the variable is set to
+ a null value.
+
+ For example, this command:
+
+ set env USER = foo
+
+ tells a Unix program, when subsequently run, that its user is named
+ `foo'. (The spaces around `=' are used for clarity here; they are
+ not actually required.)
+
+`unset environment VARNAME'
+ Remove variable VARNAME from the environment to be passed to your
+ program. This is different from `set env VARNAME ='; `unset
+ environment' removes the variable from the environment, rather
+ than assigning it an empty value.
+
+ *Warning:* GDB runs your program using the shell indicated by your
+`SHELL' environment variable if it exists (or `/bin/sh' if not). If
+your `SHELL' variable names a shell that runs an initialization
+file--such as `.cshrc' for C-shell, or `.bashrc' for BASH--any
+variables you set in that file will affect your program. You may wish
+to move setting of environment variables to files that are only run
+when you sign on, such as `.login' or `.profile'.
+
+
+File: gdb.info, Node: Working Directory, Next: Input/Output, Prev: Environment, Up: Running
+
+Your program's working directory
+================================
+
+ Each time you start your program with `run', it inherits its working
+directory from the current working directory of GDB. The GDB working
+directory is initially whatever it inherited from its parent process
+(typically the shell), but you can specify a new working directory in
+GDB with the `cd' command.
+
+ The GDB working directory also serves as a default for the commands
+that specify files for GDB to operate on. *Note Commands to specify
+files: Files.
+
+`cd DIRECTORY'
+ Set the GDB working directory to DIRECTORY.
+
+`pwd'
+ Print the GDB working directory.
+
+
+File: gdb.info, Node: Input/Output, Next: Attach, Prev: Working Directory, Up: Running
+
+Your program's input and output
+===============================
+
+ By default, the program you run under GDB does input and output to
+the same terminal that GDB uses. GDB switches the terminal to its own
+terminal modes to interact with you, but it records the terminal modes
+your program was using and switches back to them when you continue
+running your program.
+
+`info terminal'
+ Displays information recorded by GDB about the terminal modes your
+ program is using.
+
+ You can redirect your program's input and/or output using shell
+redirection with the `run' command. For example,
+
+ run > outfile
+
+starts your program, diverting its output to the file `outfile'.
+
+ Another way to specify where your program should do input and output
+is with the `tty' command. This command accepts a file name as
+argument, and causes this file to be the default for future `run'
+commands. It also resets the controlling terminal for the child
+process, for future `run' commands. For example,
+
+ tty /dev/ttyb
+
+directs that processes started with subsequent `run' commands default
+to do input and output on the terminal `/dev/ttyb' and have that as
+their controlling terminal.
+
+ An explicit redirection in `run' overrides the `tty' command's
+effect on the input/output device, but not its effect on the controlling
+terminal.
+
+ When you use the `tty' command or redirect input in the `run'
+command, only the input *for your program* is affected. The input for
+GDB still comes from your terminal.
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.info-2 b/gnu/usr.bin/gdb/doc/gdb.info-2
new file mode 100644
index 000000000000..e8be2fa7d906
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info-2
@@ -0,0 +1,1165 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+File: gdb.info, Node: Attach, Next: Kill Process, Prev: Input/Output, Up: Running
+
+Debugging an already-running process
+====================================
+
+`attach PROCESS-ID'
+ This command attaches to a running process--one that was started
+ outside GDB. (`info files' will show your active targets.) The
+ command takes as argument a process ID. The usual way to find out
+ the process-id of a Unix process is with the `ps' utility, or with
+ the `jobs -l' shell command.
+
+ `attach' will not repeat if you press RET a second time after
+ executing the command.
+
+ To use `attach', your program must be running in an environment
+which supports processes; for example, `attach' does not work for
+programs on bare-board targets that lack an operating system. You must
+also have permission to send the process a signal.
+
+ When using `attach', you should first use the `file' command to
+specify the program running in the process and load its symbol table.
+*Note Commands to Specify Files: Files.
+
+ The first thing GDB does after arranging to debug the specified
+process is to stop it. You can examine and modify an attached process
+with all the GDB commands that are ordinarily available when you start
+processes with `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 `continue' command after attaching
+GDB to the process.
+
+`detach'
+ When you have finished debugging the attached process, you can use
+ the `detach' command to release it from GDB control. Detaching
+ the process continues its execution. After the `detach' command,
+ that process and GDB become completely independent once more, and
+ you are ready to `attach' another process or start one with `run'.
+ `detach' will not repeat if you press RET again after executing
+ the command.
+
+ If you exit GDB or use the `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 you need to confirm by using the `set confirm' command
+(*note Optional warnings and messages: Messages/Warnings.).
+
+
+File: gdb.info, Node: Kill Process, Next: Process Information, Prev: Attach, Up: Running
+
+Killing the child process
+=========================
+
+`kill'
+ Kill the child process in which your program is running under GDB.
+
+ This command is useful if you wish to debug a core dump instead of a
+running process. GDB ignores any core dump file while your program is
+running.
+
+ On some operating systems, a program cannot be executed outside GDB
+while you have breakpoints set on it inside GDB. You can use the
+`kill' command in this situation to permit running your program outside
+the debugger.
+
+ The `kill' command is also useful if you wish to recompile and
+relink your program, since on many systems it is impossible to modify an
+executable file while it is running in a process. In this case, when
+you next type `run', GDB will notice that the file has changed, and
+will re-read the symbol table (while trying to preserve your current
+breakpoint settings).
+
+
+File: gdb.info, Node: Process Information, Prev: Kill Process, Up: Running
+
+Additional process information
+==============================
+
+ Some operating systems provide a facility called `/proc' that can be
+used to examine the image of a running process using file-system
+subroutines. If GDB is configured for an operating system with this
+facility, the command `info proc' is available to report on several
+kinds of information about the process running your program.
+
+`info proc'
+ Summarize available information about the process.
+
+`info proc mappings'
+ Report on the address ranges accessible in the program, with
+ information on whether your program may read, write, or execute
+ each range.
+
+`info proc times'
+ Starting time, user CPU time, and system CPU time for your program
+ and its children.
+
+`info proc id'
+ Report on the process IDs related to your program: its own process
+ ID, the ID of its parent, the process group ID, and the session ID.
+
+`info proc status'
+ General information on the state of the process. If the process is
+ stopped, this report includes the reason for stopping, and any
+ signal received.
+
+`info proc all'
+ Show all the above information about the process.
+
+
+File: gdb.info, Node: Stopping, Next: Stack, Prev: Running, Up: Top
+
+Stopping and Continuing
+***********************
+
+ The principal purposes of using a debugger are so that you can stop
+your program before it terminates; or so that, if your program runs into
+trouble, you can investigate and find out why.
+
+ Inside GDB, your program may stop for any of several reasons, such as
+a signal, a breakpoint, or reaching a new line after a GDB command such
+as `step'. You may then examine and change variables, set new
+breakpoints or remove old ones, and then continue execution. Usually,
+the messages shown by GDB provide ample explanation of the status of
+your program--but you can also explicitly request this information at
+any time.
+
+`info program'
+ Display information about the status of your program: whether it is
+ running or not, what process it is, and why it stopped.
+
+* Menu:
+
+
+* Breakpoints:: Breakpoints, watchpoints, and exceptions
+
+
+* Continuing and Stepping:: Resuming execution
+
+* Signals:: Signals
+
+
+File: gdb.info, Node: Breakpoints, Next: Continuing and Stepping, Up: Stopping
+
+Breakpoints, watchpoints, and exceptions
+========================================
+
+ A "breakpoint" makes your program stop whenever a certain point in
+the program is reached. For each breakpoint, you can add various
+conditions to control in finer detail whether your program will stop.
+You can set breakpoints with the `break' command and its variants
+(*note Setting breakpoints: Set Breaks.), to specify the place where
+your program should stop by line number, function name or exact address
+in the program. In languages with exception handling (such as GNU
+C++), you can also set breakpoints where an exception is raised (*note
+Breakpoints and exceptions: Exception Handling.).
+
+ A "watchpoint" is a special breakpoint that stops your program when
+the value of an expression changes. You must use a different command
+to set watchpoints (*note Setting watchpoints: Set Watchpoints.), but
+aside from that, you can manage a watchpoint like any other breakpoint:
+you enable, disable, and delete both breakpoints and watchpoints using
+the same commands.
+
+ You can arrange to have values from your program displayed
+automatically whenever GDB stops at a breakpoint. *Note Automatic
+display: Auto Display.
+
+ GDB assigns a number to each breakpoint or watchpoint when you
+create it; these numbers are successive integers starting with one. 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 "enabled" or "disabled"; if disabled, it has no
+effect on your program until you enable it again.
+
+* Menu:
+
+* Set Breaks:: Setting breakpoints
+* Set Watchpoints:: Setting watchpoints
+
+* Exception Handling:: Breakpoints and exceptions
+
+* Delete Breaks:: Deleting breakpoints
+* Disabling:: Disabling breakpoints
+* Conditions:: Break conditions
+* Break Commands:: Breakpoint command lists
+
+* Breakpoint Menus:: Breakpoint menus
+
+* Error in Breakpoints:: "Cannot insert breakpoints"
+
+
+File: gdb.info, Node: Set Breaks, Next: Set Watchpoints, Up: Breakpoints
+
+Setting breakpoints
+-------------------
+
+ Breakpoints are set with the `break' command (abbreviated `b'). The
+debugger convenience variable `$bpnum' records the number of the
+beakpoint you've set most recently; see *Note Convenience variables:
+Convenience Vars, for a discussion of what you can do with convenience
+variables.
+
+ You have several ways to say where the breakpoint should go.
+
+`break FUNCTION'
+ Set a breakpoint at entry to function FUNCTION. When using source
+ languages that permit overloading of symbols, such as C++,
+ FUNCTION may refer to more than one possible place to break.
+ *Note Breakpoint menus: Breakpoint Menus, for a discussion of that
+ situation.
+
+`break +OFFSET'
+`break -OFFSET'
+ Set a breakpoint some number of lines forward or back from the
+ position at which execution stopped in the currently selected
+ frame.
+
+`break LINENUM'
+ Set a breakpoint at line LINENUM in the current source file. That
+ file is the last file whose source text was printed. This
+ breakpoint will stop your program just before it executes any of
+ the code on that line.
+
+`break FILENAME:LINENUM'
+ Set a breakpoint at line LINENUM in source file FILENAME.
+
+`break FILENAME:FUNCTION'
+ Set a breakpoint at entry to function FUNCTION found in file
+ FILENAME. Specifying a file name as well as a function name is
+ superfluous except when multiple files contain similarly named
+ functions.
+
+`break *ADDRESS'
+ Set a breakpoint at address ADDRESS. You can use this to set
+ breakpoints in parts of your program which do not have debugging
+ information or source files.
+
+`break'
+ When called without any arguments, `break' sets a breakpoint at
+ the next instruction to be executed in the selected stack frame
+ (*note Examining the Stack: Stack.). In any selected frame but the
+ innermost, this will cause your program to stop as soon as control
+ returns to that frame. This is similar to the effect of a
+ `finish' command in the frame inside the selected frame--except
+ that `finish' does not leave an active breakpoint. If you use
+ `break' without an argument in the innermost frame, GDB will stop
+ the next time it reaches the current location; this may be useful
+ inside loops.
+
+ GDB 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 your program stopped.
+
+`break ... if COND'
+ Set a breakpoint with condition COND; evaluate the expression COND
+ each time the breakpoint is reached, and stop only if the value is
+ nonzero--that is, if COND evaluates as true. `...' stands for one
+ of the possible arguments described above (or no argument)
+ specifying where to break. *Note Break conditions: Conditions,
+ for more information on breakpoint conditions.
+
+`tbreak ARGS'
+ Set a breakpoint enabled only for one stop. ARGS are the same as
+ for the `break' command, and the breakpoint is set in the same
+ way, but the breakpoint is automatically disabled after the first
+ time your program stops there. *Note Disabling breakpoints:
+ Disabling.
+
+`rbreak REGEX'
+ Set breakpoints on all functions matching the regular expression
+ REGEX. 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 `break' command. They can be deleted, disabled, made
+ conditional, etc., in the standard ways.
+
+ When debugging C++ programs, `rbreak' is useful for setting
+ breakpoints on overloaded functions that are not members of any
+ special classes.
+
+`info breakpoints [N]'
+`info break [N]'
+`info watchpoints [N]'
+ Print a table of all breakpoints and watchpoints set and not
+ deleted, with the following columns for each breakpoint:
+
+ *Breakpoint Numbers*
+ *Type*
+ Breakpoint or watchpoint.
+
+ *Disposition*
+ Whether the breakpoint is marked to be disabled or deleted
+ when hit.
+
+ *Enabled or Disabled*
+ Enabled breakpoints are marked with `y'. `n' marks
+ breakpoints that are not enabled.
+
+ *Address*
+ Where the breakpoint is in your program, as a memory address
+
+ *What*
+ Where the breakpoint is in the source for your program, as a
+ file and line number.
+
+ If a breakpoint is conditional, `info break' shows the condition on
+ the line following the affected breakpoint; breakpoint commands,
+ if any, are listed after that.
+
+ `info break' with a breakpoint number N as argument lists only
+ that breakpoint. The convenience variable `$_' and the default
+ examining-address for the `x' command are set to the address of
+ the last breakpoint listed (*note Examining memory: Memory.).
+
+ GDB allows you to set any number of breakpoints at the same place in
+your program. There is nothing silly or meaningless about this. When
+the breakpoints are conditional, this is even useful (*note Break
+conditions: Conditions.).
+
+ GDB itself sometimes sets breakpoints in your program for special
+purposes, such as proper handling of `longjmp' (in C programs). These
+internal breakpoints are assigned negative numbers, starting with `-1';
+`info breakpoints' does not display them.
+
+ You can see these breakpoints with the GDB maintenance command
+`maint info breakpoints'.
+
+`maint info breakpoints'
+ Using the same format as `info breakpoints', display both the
+ breakpoints you've set explicitly, and those GDB is using for
+ internal purposes. Internal breakpoints are shown with negative
+ breakpoint numbers. The type column identifies what kind of
+ breakpoint is shown:
+
+ `breakpoint'
+ Normal, explicitly set breakpoint.
+
+ `watchpoint'
+ Normal, explicitly set watchpoint.
+
+ `longjmp'
+ Internal breakpoint, used to handle correctly stepping through
+ `longjmp' calls.
+
+ `longjmp resume'
+ Internal breakpoint at the target of a `longjmp'.
+
+ `until'
+ Temporary internal breakpoint used by the GDB `until' command.
+
+ `finish'
+ Temporary internal breakpoint used by the GDB `finish'
+ command.
+
+
+File: gdb.info, Node: Set Watchpoints, Next: Exception Handling, Prev: Set Breaks, Up: Breakpoints
+
+Setting watchpoints
+-------------------
+
+ You can use a watchpoint to stop execution whenever the value of an
+expression changes, without having to predict a particular place where
+this may happen.
+
+ Watchpoints currently execute two orders of magnitude more slowly
+than other breakpoints, but this can be well worth it to catch errors
+where you have no clue what part of your program is the culprit. Some
+processors provide special hardware to support watchpoint evaluation;
+future releases of GDB will use such hardware if it is available.
+
+`watch EXPR'
+ Set a watchpoint for an expression.
+
+`info watchpoints'
+ This command prints a list of watchpoints and breakpoints; it is
+ the same as `info break'.
+
+
+File: gdb.info, Node: Exception Handling, Next: Delete Breaks, Prev: Set Watchpoints, Up: Breakpoints
+
+Breakpoints and exceptions
+--------------------------
+
+ Some languages, such as GNU C++, implement exception handling. You
+can use GDB to examine what caused your program to raise an exception,
+and to list the exceptions your program is prepared to handle at a
+given point in time.
+
+`catch EXCEPTIONS'
+ You can set breakpoints at active exception handlers by using the
+ `catch' command. EXCEPTIONS is a list of names of exceptions to
+ catch.
+
+ You can use `info catch' to list active exception handlers. *Note
+Information about a frame: Frame Info.
+
+ There are currently some limitations to exception handling in GDB.
+These will be corrected in a future release.
+
+ * If you call a function interactively, GDB normally returns 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 you and cause your program to simply
+ continue running until it hits a breakpoint, catches a signal that
+ GDB is listening for, or exits.
+
+ * You cannot raise an exception interactively.
+
+ * You cannot interactively install an exception handler.
+
+ Sometimes `catch' is not the best way to debug exception handling:
+if you need to know exactly where an exception is raised, it is better
+to stop *before* the exception handler is called, since that way you
+can see the stack before any unwinding takes place. If you set a
+breakpoint in an exception handler instead, it may not be easy to find
+out where the exception was raised.
+
+ To stop just before an exception handler is called, you need some
+knowledge of the implementation. In the case of GNU C++, exceptions are
+raised by calling a library function named `__raise_exception' which
+has the following ANSI C interface:
+
+ /* ADDR is where the exception identifier is stored.
+ ID is the exception identifier. */
+ void __raise_exception (void **ADDR, void *ID);
+
+To make the debugger catch all exceptions before any stack unwinding
+takes place, set a breakpoint on `__raise_exception' (*note
+Breakpoints; watchpoints; and exceptions: Breakpoints.).
+
+ With a conditional breakpoint (*note Break conditions: Conditions.)
+that depends on the value of ID, you can stop your program when a
+specific exception is raised. You can use multiple conditional
+breakpoints to stop your program when any of a number of exceptions are
+raised.
+
+
+File: gdb.info, Node: Delete Breaks, Next: Disabling, Prev: Exception Handling, Up: Breakpoints
+
+Deleting breakpoints
+--------------------
+
+ It is often necessary to eliminate a breakpoint or watchpoint once it
+has done its job and you no longer want your program to stop there.
+This is called "deleting" the breakpoint. A breakpoint that has been
+deleted no longer exists; it is forgotten.
+
+ With the `clear' command you can delete breakpoints according to
+where they are in your program. With the `delete' command you can
+delete individual breakpoints or watchpoints by specifying their
+breakpoint numbers.
+
+ It is not necessary to delete a breakpoint to proceed past it. GDB
+automatically ignores breakpoints on the first instruction to be
+executed when you continue execution without changing the execution
+address.
+
+`clear'
+ Delete any breakpoints at the next instruction to be executed in
+ the selected stack frame (*note Selecting a frame: Selection.).
+ When the innermost frame is selected, this is a good way to delete
+ a breakpoint where your program just stopped.
+
+`clear FUNCTION'
+`clear FILENAME:FUNCTION'
+ Delete any breakpoints set at entry to the function FUNCTION.
+
+`clear LINENUM'
+`clear FILENAME:LINENUM'
+ Delete any breakpoints set at or within the code of the specified
+ line.
+
+`delete [breakpoints] [BNUMS...]'
+ Delete the breakpoints or watchpoints of the numbers specified as
+ arguments. If no argument is specified, delete all breakpoints
+ (GDB asks confirmation, unless you have `set confirm off'). You
+ can abbreviate this command as `d'.
+
+
+File: gdb.info, Node: Disabling, Next: Conditions, Prev: Delete Breaks, Up: Breakpoints
+
+Disabling breakpoints
+---------------------
+
+ Rather than deleting a breakpoint or watchpoint, you might prefer to
+"disable" it. This makes the breakpoint inoperative as if it had been
+deleted, but remembers the information on the breakpoint so that you
+can "enable" it again later.
+
+ You disable and enable breakpoints and watchpoints with the `enable'
+and `disable' commands, optionally specifying one or more breakpoint
+numbers as arguments. Use `info break' or `info watch' to print a list
+of breakpoints or watchpoints if you do not know which numbers to use.
+
+ A breakpoint or watchpoint can have any of four different states of
+enablement:
+
+ * Enabled. The breakpoint will stop your program. A breakpoint set
+ with the `break' command starts out in this state.
+
+ * Disabled. The breakpoint has no effect on your program.
+
+ * Enabled once. The breakpoint will stop your program, but when it
+ does so it will become disabled. A breakpoint set with the
+ `tbreak' command starts out in this state.
+
+ * Enabled for deletion. The breakpoint will stop your program, but
+ immediately after it does so it will be deleted permanently.
+
+ You can use the following commands to enable or disable breakpoints
+and watchpoints:
+
+`disable [breakpoints] [BNUMS...]'
+ 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. You may
+ abbreviate `disable' as `dis'.
+
+`enable [breakpoints] [BNUMS...]'
+ Enable the specified breakpoints (or all defined breakpoints).
+ They become effective once again in stopping your program.
+
+`enable [breakpoints] once BNUMS...'
+ Enable the specified breakpoints temporarily. Each will be
+ disabled again the next time it stops your program.
+
+`enable [breakpoints] delete BNUMS...'
+ Enable the specified breakpoints to work once and then die. Each
+ of the breakpoints will be deleted the next time it stops your
+ program.
+
+ Save for a breakpoint set with `tbreak' (*note Setting breakpoints:
+Set Breaks.), breakpoints that you set are initially enabled;
+subsequently, they become disabled or enabled only when you use one of
+the commands above. (The command `until' can set and delete a
+breakpoint of its own, but it will not change the state of your other
+breakpoints; see *Note Continuing and stepping: Continuing and
+Stepping.)
+
+
+File: gdb.info, Node: Conditions, Next: Break Commands, Prev: Disabling, Up: Breakpoints
+
+Break conditions
+----------------
+
+ The simplest sort of breakpoint breaks every time your program
+reaches a specified place. You can also specify a "condition" for a
+breakpoint. A condition is just a Boolean expression in your
+programming language (*note Expressions: Expressions.). A breakpoint
+with a condition evaluates the expression each time your program
+reaches it, and your program stops only if the condition is *true*.
+
+ This is the converse of using assertions for program validation; in
+that situation, you want to stop when the assertion is violated--that
+is, when the condition is false. In C, if you want to test an
+assertion expressed by the condition ASSERT, you should set the
+condition `! ASSERT' on the appropriate breakpoint.
+
+ Conditions are also accepted for watchpoints; you may not need them,
+since a watchpoint is inspecting the value of an expression anyhow--but
+it might be simpler, say, to just set a watchpoint on a variable name,
+and specify a condition that tests whether the new value is an
+interesting one.
+
+ Break conditions can have side effects, and may even call functions
+in your program. This can be useful, for example, to activate functions
+that log program progress, or to use your own print functions to format
+special data structures. The effects are completely predictable unless
+there is another enabled breakpoint at the same address. (In that
+case, GDB might see the other breakpoint first and stop your 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 (*note Breakpoint
+command lists: Break Commands.).
+
+ Break conditions can be specified when a breakpoint is set, by using
+`if' in the arguments to the `break' command. *Note Setting
+breakpoints: Set Breaks. They can also be changed at any time with the
+`condition' command. The `watch' command does not recognize the `if'
+keyword; `condition' is the only way to impose a further condition on a
+watchpoint.
+
+`condition BNUM EXPRESSION'
+ Specify EXPRESSION as the break condition for breakpoint or
+ watchpoint number BNUM. From now on, this breakpoint will stop
+ your program only if the value of EXPRESSION is true (nonzero, in
+ C). When you use `condition', GDB checks EXPRESSION immediately
+ for syntactic correctness, and to determine whether symbols in it
+ have referents in the context of your breakpoint. GDB does not
+ actually evaluate EXPRESSION at the time the `condition' command
+ is given, however. *Note Expressions: Expressions.
+
+`condition BNUM'
+ Remove the condition from breakpoint number BNUM. It becomes an
+ ordinary unconditional 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 "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 your 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
+N, the breakpoint will not stop the next N times it is reached.
+
+`ignore BNUM COUNT'
+ Set the ignore count of breakpoint number BNUM to COUNT. The next
+ COUNT times the breakpoint is reached, your program's execution
+ will not stop; other than to decrement the ignore count, GDB takes
+ no action.
+
+ To make the breakpoint stop the next time it is reached, specify a
+ count of zero.
+
+ When you use `continue' to resume execution of your program from a
+ breakpoint, you can specify an ignore count directly as an
+ argument to `continue', rather than using `ignore'. *Note
+ Continuing and stepping: Continuing and Stepping.
+
+ 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.
+
+ You could achieve the effect of the ignore count with a condition
+ such as `$foo-- <= 0' using a debugger convenience variable that
+ is decremented each time. *Note Convenience variables:
+ Convenience Vars.
+
+
+File: gdb.info, Node: Break Commands, Next: Breakpoint Menus, Prev: Conditions, Up: Breakpoints
+
+Breakpoint command lists
+------------------------
+
+ You can give any breakpoint (or watchpoint) a series of commands to
+execute when your program stops due to that breakpoint. For example,
+you might want to print the values of certain expressions, or enable
+other breakpoints.
+
+`commands [BNUM]'
+`... COMMAND-LIST ...'
+`end'
+ Specify a list of commands for breakpoint number BNUM. The
+ commands themselves appear on the following lines. Type a line
+ containing just `end' to terminate the commands.
+
+ To remove all commands from a breakpoint, type `commands' and
+ follow it immediately with `end'; that is, give no commands.
+
+ With no BNUM argument, `commands' refers to the last breakpoint or
+ watchpoint set (not to the breakpoint most recently encountered).
+
+ Pressing RET as a means of repeating the last GDB command is
+disabled within a COMMAND-LIST.
+
+ You can use breakpoint commands to start your program up again.
+Simply use the `continue' command, or `step', or any other command that
+resumes execution.
+
+ Any other commands in the command list, after a command that resumes
+execution, are ignored. This is because any time you resume execution
+(even with a simple `next' or `step'), you may encounter another
+breakpoint--which could have its own command list, leading to
+ambiguities about which list to execute.
+
+ If the first command you specify in a command list is `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 none of the remaining commands print anything, you
+will see no sign that the breakpoint was reached. `silent' is
+meaningful only at the beginning of a breakpoint command list.
+
+ The commands `echo', `output', and `printf' allow you to print
+precisely controlled output, and are often useful in silent
+breakpoints. *Note Commands for controlled output: Output.
+
+ For example, here is how you could use breakpoint commands to print
+the value of `x' at entry to `foo' whenever `x' is positive.
+
+ break foo if x>0
+ commands
+ silent
+ printf "x is %d\n",x
+ cont
+ end
+
+ One application for breakpoint commands is to compensate for one bug
+so you can test for 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 `continue' command so
+that your program does not stop, and start with the `silent' command so
+that no output is produced. Here is an example:
+
+ break 403
+ commands
+ silent
+ set x = y + 4
+ cont
+ end
+
+
+File: gdb.info, Node: Breakpoint Menus, Next: Error in Breakpoints, Prev: Break Commands, Up: Breakpoints
+
+Breakpoint menus
+----------------
+
+ Some programming languages (notably C++) permit a single function
+name to be defined several times, for application in different contexts.
+This is called "overloading". When a function name is overloaded,
+`break FUNCTION' is not enough to tell GDB where you want a breakpoint.
+If you realize this will be a problem, you can use something like
+`break FUNCTION(TYPES)' to specify which particular version of the
+function you want. Otherwise, GDB offers you a menu of numbered
+choices for different possible breakpoints, and waits for your
+selection with the prompt `>'. The first two options are always `[0]
+cancel' and `[1] all'. Typing `1' sets a breakpoint at each definition
+of FUNCTION, and typing `0' aborts the `break' command without setting
+any new breakpoints.
+
+ For example, the following session excerpt shows an attempt to set a
+breakpoint at the overloaded symbol `String::after'. We choose three
+particular definitions of that function name:
+
+ (gdb) b String::after
+ [0] cancel
+ [1] all
+ [2] file:String.cc; line number:867
+ [3] file:String.cc; line number:860
+ [4] file:String.cc; line number:875
+ [5] file:String.cc; line number:853
+ [6] file:String.cc; line number:846
+ [7] file:String.cc; line number:735
+ > 2 4 6
+ Breakpoint 1 at 0xb26c: file String.cc, line 867.
+ Breakpoint 2 at 0xb344: file String.cc, line 875.
+ Breakpoint 3 at 0xafcc: file String.cc, line 846.
+ Multiple breakpoints were set.
+ Use the "delete" command to delete unwanted
+ breakpoints.
+ (gdb)
+
+
+File: gdb.info, Node: Error in Breakpoints, Prev: Breakpoint Menus, Up: Breakpoints
+
+"Cannot insert breakpoints"
+---------------------------
+
+ 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
+causes GDB to stop the other process.
+
+ When this happens, you have three ways to proceed:
+
+ 1. Remove or disable the breakpoints, then continue.
+
+ 2. Suspend GDB, and copy the file containing your program to a new
+ name. Resume GDB and use the `exec-file' command to specify that
+ GDB should run your program under that name. Then start your
+ program again.
+
+ 3. Relink your program so that the text segment is nonsharable, using
+ the linker option `-N'. The operating system limitation may not
+ apply to nonsharable executables.
+
+
+File: gdb.info, Node: Continuing and Stepping, Next: Signals, Prev: Breakpoints, Up: Stopping
+
+Continuing and stepping
+=======================
+
+ "Continuing" means resuming program execution until your program
+completes normally. In contrast, "stepping" means executing just one
+more "step" of your program, where "step" may mean either one line of
+source code, or one machine instruction (depending on what particular
+command you use). Either when continuing or when stepping, your
+program may stop even sooner, due to a breakpoint or a signal. (If due
+to a signal, you may want to use `handle', or use `signal 0' to resume
+execution. *Note Signals: Signals.)
+
+`continue [IGNORE-COUNT]'
+`c [IGNORE-COUNT]'
+`fg [IGNORE-COUNT]'
+ Resume program execution, at the address where your program last
+ stopped; any breakpoints set at that address are bypassed. The
+ optional argument IGNORE-COUNT allows you to specify a further
+ number of times to ignore a breakpoint at this location; its
+ effect is like that of `ignore' (*note Break conditions:
+ Conditions.).
+
+ The argument IGNORE-COUNT is meaningful only when your program
+ stopped due to a breakpoint. At other times, the argument to
+ `continue' is ignored.
+
+ The synonyms `c' and `fg' are provided purely for convenience, and
+ have exactly the same behavior as `continue'.
+
+ To resume execution at a different place, you can use `return'
+(*note Returning from a function: Returning.) to go back to the calling
+function; or `jump' (*note Continuing at a different address: Jumping.)
+to go to an arbitrary location in your program.
+
+ A typical technique for using stepping is to set a breakpoint (*note
+Breakpoints; watchpoints; and exceptions: Breakpoints.) at the
+beginning of the function or the section of your program where a
+problem is believed to lie, run your 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.
+
+`step'
+ Continue running your program until control reaches a different
+ source line, then stop it and return control to GDB. This command
+ is abbreviated `s'.
+
+ *Warning:* If you use the `step' command while control is
+ within a function that was compiled without debugging
+ information, execution proceeds until control reaches a
+ function that does have debugging information.
+
+`step COUNT'
+ Continue running as in `step', but do so COUNT times. If a
+ breakpoint is reached, or a signal not related to stepping occurs
+ before COUNT steps, stepping stops right away.
+
+`next [COUNT]'
+ Continue to the next source line in the current (innermost) stack
+ frame. Similar to `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 `next' command was given. This
+ command is abbreviated `n'.
+
+ An argument COUNT is a repeat count, as for `step'.
+
+ `next' within a function that lacks debugging information acts like
+ `step', but any function calls appearing within the code of the
+ function are executed without stopping.
+
+`finish'
+ Continue running until just after function in the selected stack
+ frame returns. Print the returned value (if any).
+
+ Contrast this with the `return' command (*note Returning from a
+ function: Returning.).
+
+`until'
+`u'
+ 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
+ `next' command, except that when `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, `until' will cause your program to continue
+ execution until the loop is exited. In contrast, a `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.
+
+ `until' always stops your program if it attempts to exit the
+ current stack frame.
+
+ `until' may produce somewhat counterintuitive results if the order
+ of machine code does not match the order of the source lines. For
+ example, in the following excerpt from a debugging session, the `f'
+ (`frame') command shows that execution is stopped at line `206';
+ yet when we use `until', we get to line `195':
+
+ (gdb) f
+ #0 main (argc=4, argv=0xf7fffae8) at m4.c:206
+ 206 expand_input();
+ (gdb) until
+ 195 for ( ; argc > 0; NEXTARG) {
+
+ This happened because, for execution efficiency, the compiler had
+ generated code for the loop closure test at the end, rather than
+ the start, of the loop--even though the test in a C `for'-loop is
+ written before the body of the loop. The `until' command appeared
+ to step back to the beginning of the loop when it advanced to this
+ expression; however, it has not really gone to an earlier
+ statement--not in terms of the actual machine code.
+
+ `until' with no argument works by means of single instruction
+ stepping, and hence is slower than `until' with an argument.
+
+`until LOCATION'
+`u LOCATION'
+ Continue running your program until either the specified location
+ is reached, or the current stack frame returns. LOCATION is any of
+ the forms of argument acceptable to `break' (*note Setting
+ breakpoints: Set Breaks.). This form of the command uses
+ breakpoints, and hence is quicker than `until' without an argument.
+
+`stepi'
+`si'
+ Execute one machine instruction, then stop and return to the
+ debugger.
+
+ It is often useful to do `display/i $pc' when stepping by machine
+ instructions. This will cause the next instruction to be executed
+ to be displayed automatically at each stop. *Note Automatic
+ display: Auto Display.
+
+ An argument is a repeat count, as in `step'.
+
+`nexti'
+`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 `next'.
+
+
+File: gdb.info, Node: Signals, Prev: Continuing and Stepping, Up: Stopping
+
+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 `SIGINT' is the signal
+a program gets when you type an interrupt (often `C-c'); `SIGSEGV' is
+the signal a program gets from referencing a place in memory far away
+from all the areas in use; `SIGALRM' occurs when the alarm clock timer
+goes off (which happens only if your program has requested an alarm).
+
+ Some signals, including `SIGALRM', are a normal part of the
+functioning of your program. Others, such as `SIGSEGV', indicate
+errors; these signals are "fatal" (kill your program immediately) if the
+program has not specified in advance some other way to handle the
+signal. `SIGINT' does not indicate an error in your program, but it is
+normally fatal so it can carry out the purpose of the interrupt: to
+kill the program.
+
+ GDB has the ability to detect any occurrence of a signal in your
+program. You can tell GDB in advance what to do for each kind of
+signal.
+
+ Normally, GDB is set up to ignore non-erroneous signals like
+`SIGALRM' (so as not to interfere with their role in the functioning of
+your program) but to stop your program immediately whenever an error
+signal happens. You can change these settings with the `handle'
+command.
+
+`info signals'
+ Print a table of all the kinds of signals and how GDB has been
+ told to handle each one. You can use this to see the signal
+ numbers of all the defined types of signals.
+
+`handle SIGNAL KEYWORDS...'
+ Change the way GDB handles signal SIGNAL. SIGNAL can be the
+ number of a signal or its name (with or without the `SIG' at the
+ beginning). The KEYWORDS say what change to make.
+
+ The keywords allowed by the `handle' command can be abbreviated.
+Their full names are:
+
+`nostop'
+ GDB should not stop your program when this signal happens. It may
+ still print a message telling you that the signal has come in.
+
+`stop'
+ GDB should stop your program when this signal happens. This
+ implies the `print' keyword as well.
+
+`print'
+ GDB should print a message when this signal happens.
+
+`noprint'
+ GDB should not mention the occurrence of the signal at all. This
+ implies the `nostop' keyword as well.
+
+`pass'
+ GDB should allow your program to see this signal; your program
+ will be able to handle the signal, or may be terminated if the
+ signal is fatal and not handled.
+
+`nopass'
+ GDB should not allow your program to see this signal.
+
+ When a signal stops your program, the signal is not visible until you
+continue. Your program will see the signal then, if `pass' is in
+effect for the signal in question *at that time*. In other words,
+after GDB reports a signal, you can use the `handle' command with
+`pass' or `nopass' to control whether that signal will be seen by your
+program when you later continue it.
+
+ You can also use the `signal' command to prevent your 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. For example, if your 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 your program would probably terminate immediately as
+a result of the fatal signal once it saw the signal. To prevent this,
+you can continue with `signal 0'. *Note Giving your program a signal:
+Signaling.
+
+
+File: gdb.info, Node: Stack, Next: Source, Prev: Stopping, Up: Top
+
+Examining the Stack
+*******************
+
+ When your program has stopped, the first thing you need to know is
+where it stopped and how it got there.
+
+ Each time your program performs a function call, the information
+about where in your program the call was made from is saved in a block
+of data called a "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
+"call stack".
+
+ When your program stops, the GDB commands for examining the stack
+allow you to see all of this information.
+
+ One of the stack frames is "selected" by GDB and many GDB commands
+refer implicitly to the selected frame. In particular, whenever you
+ask GDB for the value of a variable in your program, the value is found
+in the selected frame. There are special GDB commands to select
+whichever frame you are interested in.
+
+ When your program stops, GDB automatically selects the currently
+executing frame and describes it briefly as the `frame' command does
+(*note Information about a frame: Frame Info.).
+
+* Menu:
+
+* Frames:: Stack frames
+* Backtrace:: Backtraces
+* Selection:: Selecting a frame
+* Frame Info:: Information on a frame
+
+* MIPS Stack:: MIPS machines and the function stack
+
+
+File: gdb.info, Node: Frames, Next: Backtrace, Up: Stack
+
+Stack frames
+============
+
+ The call stack is divided up into contiguous pieces called "stack
+frames", or "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.
+
+ When your program is started, the stack has only one frame, that of
+the function `main'. This is called the "initial" frame or the
+"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 "innermost" frame. This
+is the most recently created of all the stack frames that still exist.
+
+ 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 "frame pointer register"
+while execution is going on in that frame.
+
+ GDB assigns numbers to all existing stack frames, starting with zero
+for the innermost frame, one for the frame that called it, and so on
+upward. These numbers do not really exist in your program; they are
+assigned by GDB to give you a way of designating stack frames in GDB
+commands.
+
+ Some compilers provide a way to compile functions so that they
+operate without stack frames. (For example, the `gcc' option
+`-fomit-frame-pointer' will generate functions without a frame.) This
+is occasionally done with heavily used library functions to save the
+frame setup time. GDB has limited facilities for dealing with these
+function invocations. If the innermost function invocation has no
+stack frame, GDB will nevertheless regard it as though it had a
+separate frame, which is numbered zero as usual, allowing correct
+tracing of the function call chain. However, GDB has no provision for
+frameless functions elsewhere in the stack.
+
+
+File: gdb.info, Node: Backtrace, Next: Selection, Prev: Frames, Up: Stack
+
+Backtraces
+==========
+
+ A backtrace is a summary of how your 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.
+
+`backtrace'
+`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 `C-c'.
+
+`backtrace N'
+`bt N'
+ Similar, but print only the innermost N frames.
+
+`backtrace -N'
+`bt -N'
+ Similar, but print only the outermost N frames.
+
+ The names `where' and `info stack' (abbreviated `info s') are
+additional aliases for `backtrace'.
+
+ Each line in the backtrace shows the frame number and the function
+name. The program counter value is also shown--unless you use `set
+print address off'. The backtrace also shows the source file name and
+line number, as well as the arguments to the function. 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 `bt
+3', so it shows the innermost three frames.
+
+ #0 m4_traceon (obs=0x24eb0, argc=1, argv=0x2b8c8)
+ at builtin.c:993
+ #1 0x6e38 in expand_macro (sym=0x2b600) at macro.c:242
+ #2 0x6840 in expand_token (obs=0x0, t=177664, td=0xf7fffb08)
+ at macro.c:71
+ (More stack frames follow...)
+
+The display for frame zero does not begin with a program counter value,
+indicating that your program has stopped at the beginning of the code
+for line `993' of `builtin.c'.
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.info-3 b/gnu/usr.bin/gdb/doc/gdb.info-3
new file mode 100644
index 000000000000..aea5862a3052
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info-3
@@ -0,0 +1,1264 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+File: gdb.info, Node: Selection, Next: Frame Info, Prev: Backtrace, Up: Stack
+
+Selecting a frame
+=================
+
+ Most commands for examining the stack and other data in your 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.
+
+`frame N'
+`f N'
+ Select frame number 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 the one
+ for `main'.
+
+`frame ADDR'
+`f ADDR'
+ Select the frame at address ADDR. This is useful mainly if the
+ chaining of stack frames has been damaged by a bug, making it
+ impossible for GDB to assign numbers properly to all frames. In
+ addition, this can be useful when your program has multiple stacks
+ and switches between them.
+
+ On the SPARC architecture, `frame' needs two addresses to select
+ an arbitrary frame: a frame pointer and a stack pointer.
+
+`up N'
+ Move N frames up the stack. For positive numbers N, this advances
+ toward the outermost frame, to higher frame numbers, to frames
+ that have existed longer. N defaults to one.
+
+`down N'
+ Move N frames down the stack. For positive numbers N, this
+ advances toward the innermost frame, to lower frame numbers, to
+ frames that were created more recently. N defaults to one. You
+ may abbreviate `down' as `do'.
+
+ All of these commands end by printing two lines of output describing
+the frame. The first line shows the frame number, the function name,
+the arguments, and the source file and line number of execution in that
+frame. The second line shows the text of that source line.
+
+ For example:
+ (gdb) up
+ #1 0x22f0 in main (argc=1, argv=0xf7fffbf4, env=0xf7fffbfc)
+ at env.c:10
+ 10 read_input_file (argv[i]);
+
+ After such a printout, the `list' command with no arguments will
+print ten lines centered on the point of execution in the frame. *Note
+Printing source lines: List.
+
+`up-silently N'
+`down-silently N'
+ These two commands are variants of `up' and `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
+ GDB command scripts, where the output might be unnecessary and
+ distracting.
+
+
+File: gdb.info, Node: Frame Info, Next: MIPS Stack, Prev: Selection, Up: Stack
+
+Information about a frame
+=========================
+
+ There are several other commands to print information about the
+selected stack frame.
+
+`frame'
+`f'
+ 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 `f'. With an
+ argument, this command is used to select a stack frame. *Note
+ Selecting a frame: Selection.
+
+`info frame'
+`info f'
+ 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 language that the source code
+ corresponding to this frame was written in, 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.
+
+`info frame ADDR'
+`info f ADDR'
+ Print a verbose description of the frame at address ADDR, without
+ selecting that frame. The selected frame remains unchanged by
+ this command.
+
+`info args'
+ Print the arguments of the selected frame, each on a separate line.
+
+`info locals'
+ Print the local variables of the selected frame, each on a separate
+ line. These are all variables (declared either static or
+ automatic) accessible at the point of execution of the selected
+ frame.
+
+`info catch'
+ 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
+ `up', `down', or `frame' commands); then type `info catch'. *Note
+ Breakpoints and exceptions: Exception Handling.
+
+
+File: gdb.info, Node: MIPS Stack, Prev: Frame Info, Up: Stack
+
+MIPS machines and the function stack
+====================================
+
+ MIPS based computers use an unusual stack frame, which sometimes
+requires GDB to search backward in the object code to find the
+beginning of a function.
+
+ To improve response time (especially for embedded applications, where
+GDB may be restricted to a slow serial line for this search) you may
+want to limit the size of this search, using one of these commands:
+
+`set heuristic-fence-post LIMIT'
+ Restrict GDBN to examining at most LIMIT bytes in its search for
+ the beginning of a function. A value of `0' (the default) means
+ there is no limit.
+
+`show heuristic-fence-post'
+ Display the current limit.
+
+These commands are available *only* when GDB is configured for
+debugging programs on MIPS processors.
+
+
+File: gdb.info, Node: Source, Next: Data, Prev: Stack, Up: Top
+
+Examining Source Files
+**********************
+
+ GDB can print parts of your program's source, since the debugging
+information recorded in the program tells GDB what source files were
+used to build it. When your program stops, GDB spontaneously prints
+the line where it stopped. Likewise, when you select a stack frame
+(*note Selecting a frame: Selection.), GDB prints the line where
+execution in that frame has stopped. You can print other portions of
+source files by explicit command.
+
+ If you use GDB through its GNU Emacs interface, you may prefer to use
+Emacs facilities to view source; *note Using GDB under GNU Emacs:
+Emacs..
+
+* Menu:
+
+* List:: Printing source lines
+
+* Search:: Searching source files
+
+* Source Path:: Specifying source directories
+* Machine Code:: Source and machine code
+
+
+File: gdb.info, Node: List, Next: Search, Up: Source
+
+Printing source lines
+=====================
+
+ To print lines from a source file, use the `list' command
+(abbreviated `l'). There are several ways to specify what part of the
+file you want to print.
+
+ Here are the forms of the `list' command most commonly used:
+
+`list LINENUM'
+ Print lines centered around line number LINENUM in the current
+ source file.
+
+`list FUNCTION'
+ Print lines centered around the beginning of function FUNCTION.
+
+`list'
+ Print more lines. If the last lines printed were printed with a
+ `list' command, this prints lines following the last lines
+ printed; however, if the last line printed was a solitary line
+ printed as part of displaying a stack frame (*note Examining the
+ Stack: Stack.), this prints lines centered around that line.
+
+`list -'
+ Print lines just before the lines last printed.
+
+ By default, GDB prints ten source lines with any of these forms of
+the `list' command. You can change this using `set listsize':
+
+`set listsize COUNT'
+ Make the `list' command display COUNT source lines (unless the
+ `list' argument explicitly specifies some other number).
+
+`show listsize'
+ Display the number of lines that `list' will currently display by
+ default.
+
+ Repeating a `list' command with RET discards the argument, so it is
+equivalent to typing just `list'. This is more useful than listing the
+same lines again. An exception is made for an argument of `-'; that
+argument is preserved in repetition so that each repetition moves up in
+the source file.
+
+ In general, the `list' command expects you to supply zero, one or two
+"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 `list':
+
+`list LINESPEC'
+ Print lines centered around the line specified by LINESPEC.
+
+`list FIRST,LAST'
+ Print lines from FIRST to LAST. Both arguments are linespecs.
+
+`list ,LAST'
+ Print lines ending with LAST.
+
+`list FIRST,'
+ Print lines starting with FIRST.
+
+`list +'
+ Print lines just after the lines last printed.
+
+`list -'
+ Print lines just before the lines last printed.
+
+`list'
+ As described in the preceding table.
+
+ Here are the ways of specifying a single source line--all the kinds
+of linespec.
+
+`NUMBER'
+ Specifies line NUMBER of the current source file. When a `list'
+ command has two linespecs, this refers to the same source file as
+ the first linespec.
+
+`+OFFSET'
+ Specifies the line OFFSET lines after the last line printed. When
+ used as the second linespec in a `list' command that has two, this
+ specifies the line OFFSET lines down from the first linespec.
+
+`-OFFSET'
+ Specifies the line OFFSET lines before the last line printed.
+
+`FILENAME:NUMBER'
+ Specifies line NUMBER in the source file FILENAME.
+
+`FUNCTION'
+ Specifies the line of the open-brace that begins the body of the
+ function FUNCTION.
+
+`FILENAME:FUNCTION'
+ Specifies the line of the open-brace that begins the body of the
+ function FUNCTION in the file FILENAME. You only need the file
+ name with a function name to avoid ambiguity when there are
+ identically named functions in different source files.
+
+`*ADDRESS'
+ Specifies the line containing the program address ADDRESS.
+ ADDRESS may be any expression.
+
+
+File: gdb.info, Node: Search, Next: Source Path, Prev: List, Up: Source
+
+Searching source files
+======================
+
+ There are two commands for searching through the current source file
+for a regular expression.
+
+`forward-search REGEXP'
+`search REGEXP'
+ The command `forward-search REGEXP' checks each line, starting
+ with the one following the last line listed, for a match for
+ REGEXP. It lists the line that is found. You can use synonym
+ `search REGEXP' or abbreviate the command name as `fo'.
+
+`reverse-search REGEXP'
+ The command `reverse-search REGEXP' checks each line, starting
+ with the one before the last line listed and going backward, for a
+ match for REGEXP. It lists the line that is found. You can
+ abbreviate this command as `rev'.
+
+
+File: gdb.info, Node: Source Path, Next: Machine Code, Prev: Search, Up: Source
+
+Specifying source directories
+=============================
+
+ 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. GDB has a list of directories to search for
+source files; this is called the "source path". Each time GDB 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 *not* used for this
+purpose. Neither is the current working directory, unless it happens
+to be in the source path.
+
+ If GDB cannot find a source file in the source path, and the object
+program records a directory, GDB tries that directory too. If the
+source path is empty, and there is no record of the compilation
+directory, GDB will, as a last resort, look in the current directory.
+
+ Whenever you reset or rearrange the source path, GDB will clear out
+any information it has cached about where source files are found, where
+each line is in the file, etc.
+
+ When you start GDB, its source path is empty. To add other
+directories, use the `directory' command.
+
+`directory DIRNAME ...'
+ Add directory DIRNAME to the front of the source path. Several
+ directory names may be given to this command, separated by `:' or
+ whitespace. You may specify a directory that is already in the
+ source path; this moves it forward, so it will be searched sooner.
+
+ You can use the string `$cdir' to refer to the compilation
+ directory (if one is recorded), and `$cwd' to refer to the current
+ working directory. `$cwd' is not the same as `.'--the former
+ tracks the current working directory as it changes during your GDB
+ session, while the latter is immediately expanded to the current
+ directory at the time you add an entry to the source path.
+
+`directory'
+ Reset the source path to empty again. This requires confirmation.
+
+`show directories'
+ Print the source path: show which directories it contains.
+
+ If your source path is cluttered with directories that are no longer
+of interest, GDB may sometimes cause confusion by finding the wrong
+versions of source. You can correct the situation as follows:
+
+ 1. Use `directory' with no argument to reset the source path to empty.
+
+ 2. Use `directory' with suitable arguments to reinstall the
+ directories you want in the source path. You can add all the
+ directories in one command.
+
+
+File: gdb.info, Node: Machine Code, Prev: Source Path, Up: Source
+
+Source and machine code
+=======================
+
+ You can use the command `info line' to map source lines to program
+addresses (and vice versa), and the command `disassemble' to display a
+range of addresses as machine instructions.
+
+`info line LINESPEC'
+ Print the starting and ending addresses of the compiled code for
+ source line LINESPEC. You can specify source lines in any of the
+ ways understood by the `list' command (*note Printing source
+ lines: List.).
+
+ For example, we can use `info line' to discover the location of the
+object code for the first line of function `m4_changequote':
+
+ (gdb) info line m4_changecom
+ Line 895 of "builtin.c" starts at pc 0x634c and ends at 0x6350.
+
+We can also inquire (using `*ADDR' as the form for LINESPEC) what
+source line covers a particular address:
+ (gdb) info line *0x63ff
+ Line 926 of "builtin.c" starts at pc 0x63e4 and ends at 0x6404.
+
+ After `info line', the default address for the `x' command is
+changed to the starting address of the line, so that `x/i' is
+sufficient to begin examining the machine code (*note Examining memory:
+Memory.). Also, this address is saved as the value of the convenience
+variable `$_' (*note Convenience variables: Convenience Vars.).
+
+`disassemble'
+ This specialized command dumps 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 specify a
+ range of addresses (first inclusive, second exclusive) to dump.
+
+ We can use `disassemble' to inspect the object code range shown in
+the last `info line' example (the example shows SPARC machine
+instructions):
+
+ (gdb) disas 0x63e4 0x6404
+ Dump of assembler code from 0x63e4 to 0x6404:
+ 0x63e4 <builtin_init+5340>: ble 0x63f8 <builtin_init+5360>
+ 0x63e8 <builtin_init+5344>: sethi %hi(0x4c00), %o0
+ 0x63ec <builtin_init+5348>: ld [%i1+4], %o0
+ 0x63f0 <builtin_init+5352>: b 0x63fc <builtin_init+5364>
+ 0x63f4 <builtin_init+5356>: ld [%o0+4], %o0
+ 0x63f8 <builtin_init+5360>: or %o0, 0x1a4, %o0
+ 0x63fc <builtin_init+5364>: call 0x9288 <path_search>
+ 0x6400 <builtin_init+5368>: nop
+ End of assembler dump.
+
+
+File: gdb.info, Node: Data, Next: Languages, Prev: Source, Up: Top
+
+Examining Data
+**************
+
+ The usual way to examine data in your program is with the `print'
+command (abbreviated `p'), or its synonym `inspect'. It evaluates and
+prints the value of an expression of the language your program is
+written in (*note Using GDB with Different Languages: Languages.).
+
+`print EXP'
+`print /F EXP'
+ EXP is an expression (in the source language). By default the
+ value of EXP is printed in a format appropriate to its data type;
+ you can choose a different format by specifying `/F', where F is a
+ letter specifying the format; *note Output formats: Output
+ Formats..
+
+`print'
+`print /F'
+ If you omit EXP, GDB displays the last value again (from the
+ "value history"; *note Value history: Value History.). This
+ allows you to conveniently inspect the same value in an
+ alternative format.
+
+ A more low-level way of examining data is with the `x' command. It
+examines data in memory at a specified address and prints it in a
+specified format. *Note Examining memory: Memory.
+
+ If you are interested in information about types, or about how the
+fields of a struct or class are declared, use the `ptype EXP' command
+rather than `print'. *Note Examining the Symbol Table: Symbols.
+
+* Menu:
+
+* Expressions:: Expressions
+* Variables:: Program variables
+* Arrays:: Artificial arrays
+* Output Formats:: Output formats
+* Memory:: Examining memory
+* Auto Display:: Automatic display
+* Print Settings:: Print settings
+* Value History:: Value history
+* Convenience Vars:: Convenience variables
+* Registers:: Registers
+
+* Floating Point Hardware:: Floating point hardware
+
+
+File: gdb.info, Node: Expressions, Next: Variables, Up: Data
+
+Expressions
+===========
+
+ `print' and many other GDB commands accept an expression and compute
+its value. Any kind of constant, variable or operator defined by the
+programming language you are using is valid in an expression in GDB.
+This includes conditional expressions, function calls, casts and string
+constants. It unfortunately does not include symbols defined by
+preprocessor `#define' commands.
+
+ Because C is so widespread, most of the expressions shown in
+examples in this manual are in C. *Note Using GDB with Different
+Languages: Languages, for information on how to use expressions in other
+languages.
+
+ In this section, we discuss operators that you can use in GDB
+expressions regardless of your programming language.
+
+ 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.
+
+ GDB supports these operators in addition to those of programming
+languages:
+
+`@'
+ `@' is a binary operator for treating parts of memory as arrays.
+ *Note Artificial arrays: Arrays, for more information.
+
+`::'
+ `::' allows you to specify a variable in terms of the file or
+ function where it is defined. *Note Program variables: Variables.
+
+`{TYPE} ADDR'
+ Refers to an object of type TYPE stored at address ADDR in memory.
+ ADDR may be any expression whose value is an integer or pointer
+ (but parentheses are required around binary operators, just as in
+ a cast). This construct is allowed regardless of what kind of
+ data is normally supposed to reside at ADDR.
+
+
+File: gdb.info, Node: Variables, Next: Arrays, Prev: Expressions, Up: Data
+
+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
+(*note Selecting a frame: 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
+
+ foo (a)
+ int a;
+ {
+ bar (a);
+ {
+ int b = test ();
+ bar (b);
+ }
+ }
+
+you can examine and use the variable `a' whenever your program is
+executing within the function `foo', but you can only use or examine
+the variable `b' while your program is executing inside the block where
+`b' is declared.
+
+ There is an 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). If that
+happens, referring to that name has unpredictable effects. If you wish,
+you can specify a static variable in a particular function or file,
+using the colon-colon notation:
+
+ FILE::VARIABLE
+ FUNCTION::VARIABLE
+
+Here FILE or FUNCTION is the name of the context for the static
+VARIABLE. In the case of file names, you can use quotes to make sure
+GDB parses the file name as a single word--for example, to print a
+global value of `x' defined in `f2.c':
+
+ (gdb) p 'f2.c'::x
+
+ This use of `::' is very rarely in conflict with the very similar
+use of the same notation in C++. GDB also supports use of the C++
+scope resolution operator in GDB expressions.
+
+ *Warning:* Occasionally, a local variable may appear to have the
+ wrong value at certain points in a function--just after entry to a
+ new scope, and just before exit.
+ You may see this problem when you are stepping by machine
+instructions. This is because on most machines, it takes more than one
+instruction to set up a stack frame (including local variable
+definitions); if you are stepping by machine instructions, variables
+may appear to have the wrong values until the stack frame is completely
+built. On exit, it usually also takes more than one machine
+instruction to destroy a stack frame; after you begin stepping through
+that group of instructions, local variable definitions may be gone.
+
+
+File: gdb.info, Node: Arrays, Next: Output Formats, Prev: Variables, Up: Data
+
+Artificial arrays
+=================
+
+ 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.
+
+ You can do this by referring to a contiguous span of memory as an
+"artificial array", using the binary operator `@'. The left operand of
+`@' should be the first element of the desired array, as an individual
+object. The right operand should be the desired 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
+
+ int *array = (int *) malloc (len * sizeof (int));
+
+you can print the contents of `array' with
+
+ p *array@len
+
+ The left operand of `@' must reside in memory. Array values made
+with `@' in this way behave just like other arrays in terms of
+subscripting, and are coerced to pointers when used in expressions.
+Artificial arrays most often appear in expressions via the value history
+(*note Value history: Value History.), after printing one out.
+
+ Sometimes the artificial array mechanism is not quite enough; in
+moderately complex data structures, the elements of interest may not
+actually be adjacent--for example, if you are interested in the values
+of pointers in an array. One useful work-around in this situation is
+to use a convenience variable (*note Convenience variables: Convenience
+Vars.) as a counter in an expression that prints the first interesting
+value, and then repeat that expression via RET. For instance, suppose
+you have an array `dtab' of pointers to structures, and you are
+interested in the values of a field `fv' in each structure. Here is an
+example of what you might type:
+
+ set $i = 0
+ p dtab[$i++]->fv
+ RET
+ RET
+ ...
+
+
+File: gdb.info, Node: Output Formats, Next: Memory, Prev: Arrays, Up: Data
+
+Output formats
+==============
+
+ By default, GDB prints a value according to its data type. 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 as an
+instruction. To do these things, specify an "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
+`print' command with a slash and a format letter. The format letters
+supported are:
+
+`x'
+ Regard the bits of the value as an integer, and print the integer
+ in hexadecimal.
+
+`d'
+ Print as integer in signed decimal.
+
+`u'
+ Print as integer in unsigned decimal.
+
+`o'
+ Print as integer in octal.
+
+`t'
+ Print as integer in binary. The letter `t' stands for "two". (1)
+
+`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:
+
+ (gdb) p/a 0x54320
+ $3 = 0x54320 <_initialize_vx+396>
+
+`c'
+ Regard as an integer and print it as a character constant.
+
+`f'
+ Regard the bits of the value as a floating point number and print
+ using typical floating point syntax.
+
+ For example, to print the program counter in hex (*note
+Registers::.), type
+
+ p/x $pc
+
+Note that no space is required before the slash; this is because command
+names in GDB cannot contain a slash.
+
+ To reprint the last value in the value history with a different
+format, you can use the `print' command with just a format and no
+expression. For example, `p/x' reprints the last value in hex.
+
+ ---------- Footnotes ----------
+
+ (1) `b' cannot be used because these format letters are also used
+with the `x' command, where `b' stands for "byte"; *note Examining
+memory: Memory..
+
+
+File: gdb.info, Node: Memory, Next: Auto Display, Prev: Output Formats, Up: Data
+
+Examining memory
+================
+
+ You can use the command `x' (for "examine") to examine memory in any
+of several formats, independently of your program's data types.
+
+`x/NFU ADDR'
+`x ADDR'
+`x'
+ Use the `x' command to examine memory.
+
+ N, F, and U are all optional parameters that specify how much memory
+to display and how to format it; ADDR is an expression giving the
+address where you want to start displaying memory. If you use defaults
+for NFU, you need not type the slash `/'. Several commands set
+convenient defaults for ADDR.
+
+N, the repeat count
+ The repeat count is a decimal integer; the default is 1. It
+ specifies how much memory (counting by units U) to display.
+
+F, the display format
+ The display format is one of the formats used by `print', or `s'
+ (null-terminated string) or `i' (machine instruction). The
+ default is `x' (hexadecimal) initially, or the format from the
+ last time you used either `x' or `print'.
+
+U, the unit size
+ The unit size is any of
+
+ `b'
+ Bytes.
+
+ `h'
+ Halfwords (two bytes).
+
+ `w'
+ Words (four bytes). This is the initial default.
+
+ `g'
+ Giant words (eight bytes).
+
+ Each time you specify a unit size with `x', that size becomes the
+ default unit the next time you use `x'. (For the `s' and `i'
+ formats, the unit size is ignored and is normally not written.)
+
+ADDR, starting display address
+ ADDR is the address where you want GDB to begin displaying memory.
+ The expression need not have a pointer value (though it may); it
+ is always interpreted as an integer address of a byte of memory.
+ *Note Expressions: Expressions, for more information on
+ expressions. The default for ADDR is usually just after the last
+ address examined--but several other commands also set the default
+ address: `info breakpoints' (to the address of the last breakpoint
+ listed), `info line' (to the starting address of a line), and
+ `print' (if you use it to display a value from memory).
+
+ For example, `x/3uh 0x54320' is a request to display three halfwords
+(`h') of memory, formatted as unsigned decimal integers (`u'), starting
+at address `0x54320'. `x/4xw $sp' prints the four words (`w') of
+memory above the stack pointer (here, `$sp'; *note Registers::.) in
+hexadecimal (`x').
+
+ Since the letters indicating unit sizes are all distinct from the
+letters specifying output formats, you do not have to remember whether
+unit size or format comes first; either order will work. The output
+specifications `4xw' and `4wx' mean exactly the same thing. (However,
+the count N must come first; `wx4' will not work.)
+
+ Even though the unit size U is ignored for the formats `s' and `i',
+you might still want to use a count N; for example, `3i' specifies that
+you want to see three machine instructions, including any operands.
+The command `disassemble' gives an alternative way of inspecting
+machine instructions; *note Source and machine code: Machine Code..
+
+ All the defaults for the arguments to `x' are designed to make it
+easy to continue scanning memory with minimal specifications each time
+you use `x'. For example, after you have inspected three machine
+instructions with `x/3i ADDR', you can inspect the next seven with just
+`x/7'. If you use RET to repeat the `x' command, the repeat count N is
+used again; the other arguments default as for successive uses of `x'.
+
+ The addresses and contents printed by the `x' command are not saved
+in the value history because there is often too much of them and they
+would get in the way. Instead, GDB makes these values available for
+subsequent use in expressions as values of the convenience variables
+`$_' and `$__'. After an `x' command, the last address examined is
+available for use in expressions in the convenience variable `$_'. The
+contents of that address, as examined, are available in the convenience
+variable `$__'.
+
+ If the `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.
+
+
+File: gdb.info, Node: Auto Display, Next: Print Settings, Prev: Memory, Up: Data
+
+Automatic display
+=================
+
+ 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
+"automatic display list" so that GDB will print its value each time
+your 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:
+
+ 2: foo = 38
+ 3: bar[5] = (struct hack *) 0x3804
+
+This display shows item numbers, expressions and their current values.
+As with displays you request manually using `x' or `print', you can
+specify the output format you prefer; in fact, `display' decides
+whether to use `print' or `x' depending on how elaborate your format
+specification is--it uses `x' if you specify a unit size, or one of the
+two formats (`i' and `s') that are only supported by `x'; otherwise it
+uses `print'.
+
+`display EXP'
+ Add the expression EXP to the list of expressions to display each
+ time your program stops. *Note Expressions: Expressions.
+
+ `display' will not repeat if you press RET again after using it.
+
+`display/FMT EXP'
+ For FMT specifying only a display format and not a size or count,
+ add the expression EXP to the auto-display list but arrange to
+ display it each time in the specified format FMT. *Note Output
+ formats: Output Formats.
+
+`display/FMT ADDR'
+ For FMT `i' or `s', or including a unit-size or a number of units,
+ add the expression ADDR as a memory address to be examined each
+ time your program stops. Examining means in effect doing `x/FMT
+ ADDR'. *Note Examining memory: Memory.
+
+ For example, `display/i $pc' can be helpful, to see the machine
+instruction about to be executed each time execution stops (`$pc' is a
+common name for the program counter; *note Registers::.).
+
+`undisplay DNUMS...'
+`delete display DNUMS...'
+ Remove item numbers DNUMS from the list of expressions to display.
+
+ `undisplay' will not repeat if you press RET after using it.
+ (Otherwise you would just get the error `No display number ...'.)
+
+`disable display DNUMS...'
+ Disable the display of item numbers DNUMS. A disabled display
+ item is not printed automatically, but is not forgotten. It may be
+ enabled again later.
+
+`enable display DNUMS...'
+ Enable display of item numbers DNUMS. It becomes effective once
+ again in auto display of its expression, until you specify
+ otherwise.
+
+`display'
+ Display the current values of the expressions on the list, just as
+ is done when your program stops.
+
+`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.
+
+ 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
+`display last_char' while inside a function with an argument
+`last_char', then this argument will be displayed while your program
+continues to stop inside that function. When it stops elsewhere--where
+there is no variable `last_char'--display is disabled. The next time
+your program stops where `last_char' is meaningful, you can enable the
+display expression once again.
+
+
+File: gdb.info, Node: Print Settings, Next: Value History, Prev: Auto Display, Up: Data
+
+Print settings
+==============
+
+ GDB provides the following ways to control how arrays, structures,
+and symbols are printed.
+
+These settings are useful for debugging programs in any language:
+
+`set print address'
+`set print address on'
+ GDB will print memory addresses showing the location of stack
+ traces, structure values, pointer values, breakpoints, and so
+ forth, even when it also displays the contents of those addresses.
+ The default is on. For example, this is what a stack frame
+ display looks like, with `set print address on':
+
+ (gdb) f
+ #0 set_quotes (lq=0x34c78 "<<", rq=0x34c88 ">>")
+ at input.c:530
+ 530 if (lquote != def_lquote)
+
+`set print address off'
+ Do not print addresses when displaying their contents. For
+ example, this is the same stack frame displayed with `set print
+ address off':
+
+ (gdb) set print addr off
+ (gdb) f
+ #0 set_quotes (lq="<<", rq=">>") at input.c:530
+ 530 if (lquote != def_lquote)
+
+ You can use `set print address off' to eliminate all machine
+ dependent displays from the GDB interface. For example, with
+ `print address off', you should get the same text for backtraces on
+ all machines--whether or not they involve pointer arguments.
+
+`show print address'
+ Show whether or not addresses are to be printed.
+
+ When GDB prints a symbolic address, it normally prints the closest
+earlier symbol plus an offset. If that symbol does not uniquely
+identify the address (for example, it is a name whose scope is a single
+source file), you may need to disambiguate. One way to do this is with
+`info line', for example `info line *0x4537'. Alternately, you can set
+GDB to print the source file and line number when it prints a symbolic
+address:
+
+`set print symbol-filename on'
+ Tell GDB to print the source file name and line number of a symbol
+ in the symbolic form of an address.
+
+`set print symbol-filename off'
+ Do not print source file name and line number of a symbol. This
+ is the default.
+
+`show print symbol-filename'
+ Show whether or not GDB will print the source file name and line
+ number of a symbol in the symbolic form of an address.
+
+ Also, you may wish to see the symbolic form only if the address being
+printed is reasonably close to the closest earlier symbol:
+
+`set print max-symbolic-offset MAX-OFFSET'
+ Tell GDB to only display the symbolic form of an address if the
+ offset between the closest earlier symbol and the address is less
+ than MAX-OFFSET. The default is 0, which means to always print the
+ symbolic form of an address, if any symbol precedes it.
+
+`show print max-symbolic-offset'
+ Ask how large the maximum offset is that GDB will print in a
+ symbolic address.
+
+`set print array'
+`set print array on'
+ GDB will pretty-print arrays. This format is more convenient to
+ read, but uses more space. The default is off.
+
+`set print array off'
+ Return to compressed format for arrays.
+
+`show print array'
+ Show whether compressed or pretty format is selected for displaying
+ arrays.
+
+`set print elements NUMBER-OF-ELEMENTS'
+ If GDB is printing a large array, it will stop printing after it
+ has printed the number of elements set by the `set print elements'
+ command. This limit also applies to the display of strings.
+ Setting the number of elements to zero means that the printing is
+ unlimited.
+
+`show print elements'
+ Display the number of elements of a large array that GDB will print
+ before losing patience.
+
+`set print pretty on'
+ Cause GDB to print structures in an indented format with one
+ member per line, like this:
+
+ $1 = {
+ next = 0x0,
+ flags = {
+ sweet = 1,
+ sour = 1
+ },
+ meat = 0x54 "Pork"
+ }
+
+`set print pretty off'
+ Cause GDB to print structures in a compact format, like this:
+
+ $1 = {next = 0x0, flags = {sweet = 1, sour = 1}, \
+ meat = 0x54 "Pork"}
+
+ This is the default format.
+
+`show print pretty'
+ Show which format GDB will use to print structures.
+
+`set print sevenbit-strings on'
+ Print using only seven-bit characters; if this option is set, GDB
+ will display any eight-bit characters (in strings or character
+ values) using the notation `\'NNN. For example, `M-a' is
+ displayed as `\341'.
+
+`set print sevenbit-strings off'
+ Print using either seven-bit or eight-bit characters, as required.
+ This is the default.
+
+`show print sevenbit-strings'
+ Show whether or not GDB will print only seven-bit characters.
+
+`set print union on'
+ Tell GDB to print unions which are contained in structures. This
+ is the default setting.
+
+`set print union off'
+ Tell GDB not to print unions which are contained in structures.
+
+`show print union'
+ Ask GDB whether or not it will print unions which are contained in
+ structures.
+
+ For example, given the declarations
+
+ 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}};
+
+ with `set print union on' in effect `p foo' would print
+
+ $1 = {it = Tree, form = {tree = Acorn, bug = Cocoon}}
+
+ and with `set print union off' in effect it would print
+
+ $1 = {it = Tree, form = {...}}
+
+These settings are of interest when debugging C++ programs:
+
+`set print demangle'
+`set print demangle on'
+ Print C++ names in their source form rather than in the encoded
+ ("mangled") form passed to the assembler and linker for type-safe
+ linkage. The default is `on'.
+
+`show print demangle'
+ Show whether C++ names will be printed in mangled or demangled
+ form.
+
+`set print asm-demangle'
+`set print asm-demangle on'
+ 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.
+
+`show print asm-demangle'
+ Show whether C++ names in assembly listings will be printed in
+ mangled or demangled form.
+
+`set demangle-style STYLE'
+ Choose among several encoding schemes used by different compilers
+ to represent C++ names. The choices for STYLE are currently:
+
+ `auto'
+ Allow GDB to choose a decoding style by inspecting your
+ program.
+
+ `gnu'
+ Decode based on the GNU C++ compiler (`g++') encoding
+ algorithm.
+
+ `lucid'
+ Decode based on the Lucid C++ compiler (`lcc') encoding
+ algorithm.
+
+ `arm'
+ Decode using the algorithm in the `C++ Annotated Reference
+ Manual'. *Warning:* this setting alone is not sufficient to
+ allow debugging `cfront'-generated executables. GDB would
+ require further enhancement to permit that.
+
+`show demangle-style'
+ Display the encoding style currently in use for decoding C++
+ symbols.
+
+`set print object'
+`set print object on'
+ When displaying a pointer to an object, identify the *actual*
+ (derived) type of the object rather than the *declared* type, using
+ the virtual function table.
+
+`set print object off'
+ Display only the declared type of objects, without reference to the
+ virtual function table. This is the default setting.
+
+`show print object'
+ Show whether actual, or declared, object types will be displayed.
+
+`set print vtbl'
+`set print vtbl on'
+ Pretty print C++ virtual function tables. The default is off.
+
+`set print vtbl off'
+ Do not pretty print C++ virtual function tables.
+
+`show print vtbl'
+ Show whether C++ virtual function tables are pretty printed, or
+ not.
+
+
+File: gdb.info, Node: Value History, Next: Convenience Vars, Prev: Print Settings, Up: Data
+
+Value history
+=============
+
+ Values printed by the `print' command are saved in the GDB "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 `file' or `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.
+
+ The values printed are given "history numbers" by which you can
+refer to them. These are successive integers starting with one.
+`print' shows you the history number assigned to a value by printing
+`$NUM = ' before the value; here NUM is the history number.
+
+ To refer to any previous value, use `$' followed by the value's
+history number. The way `print' labels its output is designed to
+remind you of this. Just `$' refers to the most recent value in the
+history, and `$$' refers to the value before that. `$$N' refers to the
+Nth value from the end; `$$2' is the value just prior to `$$', `$$1' is
+equivalent to `$$', and `$$0' is equivalent to `$'.
+
+ 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
+
+ p *$
+
+ If you have a chain of structures where the component `next' points
+to the next one, you can print the contents of the next one with this:
+
+ p *$.next
+
+You can print successive links in the chain by repeating this
+command--which you can do by just typing RET.
+
+ Note that the history records values, not expressions. If the value
+of `x' is 4 and you type these commands:
+
+ print x
+ set x=5
+
+then the value recorded in the value history by the `print' command
+remains 4 even though the value of `x' has changed.
+
+`show values'
+ Print the last ten values in the value history, with their item
+ numbers. This is like `p $$9' repeated ten times, except that
+ `show values' does not change the history.
+
+`show values N'
+ Print ten history values centered on history item number N.
+
+`show values +'
+ Print ten history values just after the values last printed. If
+ no more values are available, produces no display.
+
+ Pressing RET to repeat `show values N' has exactly the same effect
+as `show values +'.
+
+
+File: gdb.info, Node: Convenience Vars, Next: Registers, Prev: Value History, Up: Data
+
+Convenience variables
+=====================
+
+ GDB provides "convenience variables" that you can use within GDB to
+hold on to a value and refer to it later. These variables exist
+entirely within GDB; they are not part of your program, and setting a
+convenience variable has no direct effect on further execution of your
+program. That is why you can use them freely.
+
+ Convenience variables are prefixed with `$'. Any name preceded by
+`$' can be used for a convenience variable, unless it is one of the
+predefined machine-specific register names (*note Registers::.).
+(Value history references, in contrast, are *numbers* preceded by `$'.
+*Note Value history: Value History.)
+
+ You can save a value in a convenience variable with an assignment
+expression, just as you would set a variable in your program. For
+example:
+
+ set $foo = *object_ptr
+
+would save in `$foo' the value contained in the object pointed to by
+`object_ptr'.
+
+ Using a convenience variable for the first time creates it, but its
+value is `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.
+
+`show convenience'
+ Print a list of convenience variables used so far, and their
+ values. Abbreviated `show con'.
+
+ 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:
+
+ set $i = 0
+ print bar[$i++]->contents
+ ... repeat that command by typing RET.
+
+ Some convenience variables are created automatically by GDB and given
+values likely to be useful.
+
+`$_'
+ The variable `$_' is automatically set by the `x' command to the
+ last address examined (*note Examining memory: Memory.). Other
+ commands which provide a default address for `x' to examine also
+ set `$_' to that address; these commands include `info line' and
+ `info breakpoint'. The type of `$_' is `void *' except when set
+ by the `x' command, in which case it is a pointer to the type of
+ `$__'.
+
+`$__'
+ The variable `$__' is automatically set by the `x' command to the
+ value found in the last address examined. Its type is chosen to
+ match the format in which the data was printed.
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.info-4 b/gnu/usr.bin/gdb/doc/gdb.info-4
new file mode 100644
index 000000000000..b0758fa5ef6a
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info-4
@@ -0,0 +1,1349 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+File: gdb.info, Node: Registers, Next: Floating Point Hardware, Prev: Convenience Vars, Up: Data
+
+Registers
+=========
+
+ You can refer to machine register contents, in expressions, as
+variables with names starting with `$'. The names of registers are
+different for each machine; use `info registers' to see the names used
+on your machine.
+
+`info registers'
+ Print the names and values of all registers except floating-point
+ registers (in the selected stack frame).
+
+`info all-registers'
+ Print the names and values of all registers, including
+ floating-point registers.
+
+`info registers REGNAME ...'
+ Print the relativized value of each specified register REGNAME.
+ rEGNAME may be any register name valid on the machine you are
+ using, with or without the initial `$'.
+
+ GDB has four "standard" register names that are available (in
+expressions) on most machines--whenever they do not conflict with an
+architecture's canonical mnemonics for registers. The register names
+`$pc' and `$sp' are used for the program counter register and the stack
+pointer. `$fp' is used for a register that contains a pointer to the
+current stack frame, and `$ps' is used for a register that contains the
+processor status. For example, you could print the program counter in
+hex with
+
+ p/x $pc
+
+or print the instruction to be executed next with
+
+ x/i $pc
+
+or add four to the stack pointer(1) with
+
+ set $sp += 4
+
+ Whenever possible, these four standard register names are available
+on your machine even though the machine has different canonical
+mnemonics, so long as there is no conflict. The `info registers'
+command shows the canonical names. For example, on the SPARC, `info
+registers' displays the processor status register as `$psr' but you can
+also refer to it as `$ps'.
+
+ GDB 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 *print* it as a floating point value with `print/f
+$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,
+GDB normally works with the virtual format only (the format that makes
+sense for your program), but the `info registers' command prints the
+data in both formats.
+
+ Normally, register values are relative to the selected stack frame
+(*note Selecting a frame: 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
+true contents of hardware registers, you must select the innermost
+frame (with `frame 0').
+
+ However, GDB must deduce where registers are saved, from the machine
+code generated by your compiler. If some registers are not saved, or if
+GDB is unable to locate the saved registers, the selected stack frame
+will make no difference.
+
+`set rstack_high_address ADDRESS'
+ On AMD 29000 family processors, registers are saved in a separate
+ "register stack". There is no way for GDB to determine the extent
+ of this stack. Normally, GDB just assumes that the stack is "large
+ enough". This may result in GDB referencing memory locations that
+ do not exist. If necessary, you can get around this problem by
+ specifying the ending address of the register stack with the `set
+ rstack_high_address' command. The argument should be an address,
+ which you will probably want to precede with `0x' to specify in
+ hexadecimal.
+
+`show rstack_high_address'
+ Display the current limit of the register stack, on AMD 29000
+ family processors.
+
+ ---------- Footnotes ----------
+
+ (1) This 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 `$sp' is
+not allowed when other stack frames are selected. To pop entire frames
+off the stack, regardless of machine architecture, use `return'; *note
+Returning from a function: Returning..
+
+
+File: gdb.info, Node: Floating Point Hardware, Prev: Registers, Up: Data
+
+Floating point hardware
+=======================
+
+ Depending on the host machine architecture, GDB may be able to give
+you more information about the status of the floating point hardware.
+
+`info float'
+ Display hardware-dependent information about the floating point
+ unit. The exact contents and layout vary depending on the
+ floating point chip; on some platforms, `info float' is not
+ available at all.
+
+
+File: gdb.info, Node: Languages, Next: Symbols, Prev: Data, Up: Top
+
+Using GDB with Different Languages
+**********************************
+
+ Although programming languages generally have common aspects, they
+are rarely expressed in the same manner. For instance, in ANSI C,
+dereferencing a pointer `p' is accomplished by `*p', but in Modula-2,
+it is accomplished by `p^'. Values can also be represented (and
+displayed) differently. Hex numbers in C are written like `0x1ae',
+while in Modula-2 they appear as `1AEH'.
+
+ Language-specific information is built into GDB for some languages,
+allowing you to express operations like the above in your program's
+native language, and allowing GDB to output values in a manner
+consistent with the syntax of your program's native language. The
+language you use to build expressions, called the "working language",
+can be selected manually, or GDB can set it automatically.
+
+* Menu:
+
+* Setting:: Switching between source languages
+* Show:: Displaying the language
+
+* Checks:: Type and range checks
+
+* Support:: Supported languages
+
+
+File: gdb.info, Node: Setting, Next: Show, Up: Languages
+
+Switching between source languages
+==================================
+
+ There are two ways to control the working language--either have GDB
+set it automatically, or select it manually yourself. You can use the
+`set language' command for either purpose. On startup, GDB defaults to
+setting the language automatically.
+
+* Menu:
+
+* Manually:: Setting the working language manually
+* Automatically:: Having GDB infer the source language
+
+
+File: gdb.info, Node: Manually, Next: Automatically, Up: Setting
+
+Setting the working language
+----------------------------
+
+ If you allow GDB to set the language automatically, expressions are
+interpreted the same way in your debugging session and your program.
+
+ If you wish, you may set the language manually. To do this, issue
+the command `set language LANG', where LANG is the name of a language,
+such as `c' or `modula-2'. For a list of the supported languages, type
+`set language'.
+
+ Setting the language manually prevents GDB from updating the working
+language automatically. This can lead to confusion if you try to debug
+a program when the working language is not the same as the source
+language, when an expression is acceptable to both languages--but means
+different things. For instance, if the current source file were
+written in C, and GDB was parsing Modula-2, a command such as:
+
+ print a = b + c
+
+might not have the effect you intended. In C, this means to add `b'
+and `c' and place the result in `a'. The result printed would be the
+value of `a'. In Modula-2, this means to compare `a' to the result of
+`b+c', yielding a `BOOLEAN' value.
+
+
+File: gdb.info, Node: Automatically, Prev: Manually, Up: Setting
+
+Having GDB infer the source language
+------------------------------------
+
+ To have GDB set the working language automatically, use `set
+language local' or `set language auto'. GDB then infers the language
+that a program was written in by looking at the name of its source
+files, and examining their extensions:
+
+`*.mod'
+ Modula-2 source file
+
+`*.c'
+ C source file
+
+`*.C'
+`*.cc'
+ C++ source file
+
+ This information is recorded for each function or procedure in a
+source file. When your program stops in a frame (usually by
+encountering a breakpoint), GDB sets the working language to the
+language recorded for the function in that frame. If the language for
+a frame is unknown (that is, if the function or block corresponding to
+the frame was defined in a source file that does not have a recognized
+extension), the current working language is not changed, and GDB issues
+a warning.
+
+ This may not seem necessary for most programs, which are written
+entirely in one source language. However, program modules and libraries
+written in one source language can be used by a main program written in
+a different source language. Using `set language auto' in this case
+frees you from having to set the working language manually.
+
+
+File: gdb.info, Node: Show, Next: Checks, Prev: Setting, Up: Languages
+
+Displaying the language
+=======================
+
+ The following commands will help you find out which language is the
+working language, and also what language source files were written in.
+
+`show language'
+ Display the current working language. This is the language you
+ can use with commands such as `print' to build and compute
+ expressions that may involve variables in your program.
+
+`info frame'
+ Among the other information listed here (*note Information about a
+ frame: Frame Info.) is the source language for this frame. This
+ is the language that will become the working language if you ever
+ use an identifier that is in this frame.
+
+`info source'
+ Among the other information listed here (*note Examining the
+ Symbol Table: Symbols.) is the source language of this source file.
+
+
+File: gdb.info, Node: Checks, Next: Support, Prev: Show, Up: Languages
+
+Type and range checking
+=======================
+
+ *Warning:* In this release, the GDB commands for type and range
+ checking are included, but they do not yet have any effect. This
+ section documents the intended facilities.
+
+ Some languages are designed to guard you against making seemingly
+common errors through a series of compile- and run-time checks. These
+include checking the type of arguments to functions and operators, and
+making sure mathematical overflows are caught at run time. Checks such
+as these help to ensure a program's correctness once it has been
+compiled by eliminating type mismatches, and providing active checks
+for range errors when your program is running.
+
+ GDB can check for conditions like the above if you wish. Although
+GDB will not check the statements in your program, it can check
+expressions entered directly into GDB for evaluation via the `print'
+command, for example. As with the working language, GDB can also
+decide whether or not to check automatically based on your program's
+source language. *Note Supported languages: Support, for the default
+settings of supported languages.
+
+* Menu:
+
+* Type Checking:: An overview of type checking
+* Range Checking:: An overview of range checking
+
+
+File: gdb.info, Node: Type Checking, Next: Range Checking, Up: Checks
+
+An overview of type checking
+----------------------------
+
+ Some languages, such as Modula-2, are strongly typed, meaning that
+the arguments to operators and functions have to be of the correct type,
+otherwise an error occurs. These checks prevent type mismatch errors
+from ever causing any run-time problems. For example,
+
+ 1 + 2 => 3
+but
+ error--> 1 + 2.3
+
+ The second example fails because the `CARDINAL' 1 is not
+type-compatible with the `REAL' 2.3.
+
+ For expressions you use in GDB commands, you can tell the GDB type
+checker to skip checking; to treat any mismatches as errors and abandon
+the expression; or only issue warnings when type mismatches occur, but
+evaluate the expression anyway. When you choose the last of these, GDB
+evaluates expressions like the second example above, but also issues a
+warning.
+
+ Even though you may turn type checking off, other type-based reasons
+may prevent GDB from evaluating an expression. For instance, GDB does
+not know how to add an `int' and a `struct foo'. These particular type
+errors have nothing to do with the language in use, and usually arise
+from expressions, such as the one described above, which make little
+sense to evaluate anyway.
+
+ Each language defines to what degree it is strict about type. For
+instance, both Modula-2 and C require the arguments to arithmetical
+operators to be numbers. In C, enumerated types and pointers can be
+represented as numbers, so that they are valid arguments to mathematical
+operators. *Note Supported languages: Support, for further details on
+specific languages.
+
+ GDB provides some additional commands for controlling the type
+checker:
+
+`set check type auto'
+ Set type checking on or off based on the current working language.
+ *Note Supported languages: Support, for the default settings for
+ each language.
+
+`set check type on'
+`set check type off'
+ Set type checking on or off, overriding the default setting for the
+ current working language. Issue a warning if the setting does not
+ match the language default. If any type mismatches occur in
+ evaluating an expression while typechecking is on, GDB prints a
+ message and aborts evaluation of the expression.
+
+`set check type warn'
+ Cause the type checker to issue warnings, but to always attempt to
+ evaluate the expression. Evaluating the expression may still be
+ impossible for other reasons. For example, GDB cannot add numbers
+ and structures.
+
+`show type'
+ Show the current setting of the type checker, and whether or not
+ GDB is setting it automatically.
+
+
+File: gdb.info, Node: Range Checking, Prev: Type Checking, Up: Checks
+
+An overview of range checking
+-----------------------------
+
+ In some languages (such as Modula-2), it is an error to exceed the
+bounds of a type; this is enforced with run-time checks. Such range
+checking is meant to ensure program correctness by making sure
+computations do not overflow, or indices on an array element access do
+not exceed the bounds of the array.
+
+ For expressions you use in GDB commands, you can tell GDB to treat
+range errors in one of three ways: ignore them, always treat them as
+errors and abandon the expression, or issue warnings but evaluate the
+expression anyway.
+
+ A range error can result from numerical overflow, from exceeding an
+array index bound, or when you type a constant that is not a member of
+any type. Some languages, however, do not treat overflows as an error.
+In many implementations of C, mathematical overflow causes the result
+to "wrap around" to lower values--for example, if M is the largest
+integer value, and S is the smallest, then
+
+ M + 1 => S
+
+ This, too, is specific to individual languages, and in some cases
+specific to individual compilers or machines. *Note Supported
+languages: Support, for further details on specific languages.
+
+ GDB provides some additional commands for controlling the range
+checker:
+
+`set check range auto'
+ Set range checking on or off based on the current working language.
+ *Note Supported languages: Support, for the default settings for
+ each language.
+
+`set check range on'
+`set check range off'
+ Set range checking on or off, overriding the default setting for
+ the current working language. A warning is issued if the setting
+ does not match the language default. If a range error occurs,
+ then a message is printed and evaluation of the expression is
+ aborted.
+
+`set check range warn'
+ Output messages when the GDB range checker detects a range error,
+ but attempt to evaluate the expression anyway. Evaluating the
+ expression may still be impossible for other reasons, such as
+ accessing memory that the process does not own (a typical example
+ from many Unix systems).
+
+`show range'
+ Show the current setting of the range checker, and whether or not
+ it is being set automatically by GDB.
+
+
+File: gdb.info, Node: Support, Prev: Checks, Up: Languages
+
+Supported languages
+===================
+
+ GDB 4 supports C, C++, and Modula-2. Some GDB features may be used
+in expressions regardless of the language you use: the GDB `@' and `::'
+operators, and the `{type}addr' construct (*note Expressions:
+Expressions.) can be used with the constructs of any supported language.
+
+ The following sections detail to what degree each source language is
+supported by GDB. These sections are not meant to be language
+tutorials or references, but serve only as a reference guide to what the
+GDB expression parser will accept, and what input and output formats
+should look like for different languages. There are many good books
+written on each of these languages; please look to these for a language
+reference or tutorial.
+
+* Menu:
+
+* C:: C and C++
+* Modula-2:: Modula-2
+
+
+File: gdb.info, Node: C, Next: Modula-2, Up: Support
+
+C and C++
+---------
+
+ Since C and C++ are so closely related, many features of GDB apply
+to both languages. Whenever this is the case, we discuss both languages
+together.
+
+ The C++ debugging facilities are jointly implemented by the GNU C++
+compiler and GDB. Therefore, to debug your C++ code effectively, you
+must compile your C++ programs with the GNU C++ compiler, `g++'.
+
+* Menu:
+
+* C Operators:: C and C++ operators
+* C Constants:: C and C++ constants
+* Cplus expressions:: C++ expressions
+* C Defaults:: Default settings for C and C++
+
+* C Checks:: C and C++ type and range checks
+
+* Debugging C:: GDB and C
+* Debugging C plus plus:: Special features for C++
+
+
+File: gdb.info, Node: C Operators, Next: C Constants, Up: C
+
+C and C++ operators
+-------------------
+
+ Operators must be defined on values of specific types. For instance,
+`+' is defined on numbers, but not on structures. Operators are often
+defined on groups of types.
+
+ For the purposes of C and C++, the following definitions hold:
+
+ * *Integral types* include `int' with any of its storage-class
+ specifiers; `char'; and `enum'.
+
+ * *Floating-point types* include `float' and `double'.
+
+ * *Pointer types* include all types defined as `(TYPE *)'.
+
+ * *Scalar types* include all of the above.
+
+The following operators are supported. They are listed here in order
+of increasing precedence:
+
+`,'
+ The comma or sequencing operator. Expressions in a
+ comma-separated list are evaluated from left to right, with the
+ result of the entire expression being the last expression
+ evaluated.
+
+`='
+ Assignment. The value of an assignment expression is the value
+ assigned. Defined on scalar types.
+
+`OP='
+ Used in an expression of the form `A OP= B', and translated to
+ `A = A OP B'. `OP=' and `=' have the same precendence. OP is any
+ one of the operators `|', `^', `&', `<<', `>>', `+', `-', `*',
+ `/', `%'.
+
+`?:'
+ The ternary operator. `A ? B : C' can be thought of as: if A
+ then B else C. A should be of an integral type.
+
+`||'
+ Logical OR. Defined on integral types.
+
+`&&'
+ Logical AND. Defined on integral types.
+
+`|'
+ Bitwise OR. Defined on integral types.
+
+`^'
+ Bitwise exclusive-OR. Defined on integral types.
+
+`&'
+ Bitwise AND. Defined on integral types.
+
+`==, !='
+ Equality and inequality. Defined on scalar types. The value of
+ these expressions is 0 for false and non-zero for true.
+
+`<, >, <=, >='
+ Less than, greater than, less than or equal, greater than or equal.
+ Defined on scalar types. The value of these expressions is 0 for
+ false and non-zero for true.
+
+`<<, >>'
+ left shift, and right shift. Defined on integral types.
+
+`@'
+ The GDB "artificial array" operator (*note Expressions:
+ Expressions.).
+
+`+, -'
+ Addition and subtraction. Defined on integral types,
+ floating-point types and pointer types.
+
+`*, /, %'
+ Multiplication, division, and modulus. Multiplication and
+ division are defined on integral and floating-point types.
+ Modulus is defined on integral types.
+
+`++, --'
+ Increment and decrement. When appearing before a variable, the
+ operation is performed before the variable is used in an
+ expression; when appearing after it, the variable's value is used
+ before the operation takes place.
+
+`*'
+ Pointer dereferencing. Defined on pointer types. Same precedence
+ as `++'.
+
+`&'
+ Address operator. Defined on variables. Same precedence as `++'.
+
+ For debugging C++, GDB implements a use of `&' beyond what is
+ allowed in the C++ language itself: you can use `&(&REF)' (or, if
+ you prefer, simply `&&REF') to examine the address where a C++
+ reference variable (declared with `&REF') is stored.
+
+`-'
+ Negative. Defined on integral and floating-point types. Same
+ precedence as `++'.
+
+`!'
+ Logical negation. Defined on integral types. Same precedence as
+ `++'.
+
+`~'
+ Bitwise complement operator. Defined on integral types. Same
+ precedence as `++'.
+
+`., ->'
+ Structure member, and pointer-to-structure member. For
+ convenience, GDB regards the two as equivalent, choosing whether
+ to dereference a pointer based on the stored type information.
+ Defined on `struct' and `union' data.
+
+`[]'
+ Array indexing. `A[I]' is defined as `*(A+I)'. Same precedence
+ as `->'.
+
+`()'
+ Function parameter list. Same precedence as `->'.
+
+`::'
+ C++ scope resolution operator. Defined on `struct', `union', and
+ `class' types.
+
+`::'
+ Doubled colons also represent the GDB scope operator (*note
+ Expressions: Expressions.). Same precedence as `::', above.
+
+
+File: gdb.info, Node: C Constants, Next: Cplus expressions, Prev: C Operators, Up: C
+
+C and C++ constants
+-------------------
+
+ GDB allows you to express the constants of C and C++ in the
+following ways:
+
+ * Integer constants are a sequence of digits. Octal constants are
+ specified by a leading `0' (ie. zero), and hexadecimal constants by
+ a leading `0x' or `0X'. Constants may also end with a letter `l',
+ specifying that the constant should be treated as a `long' value.
+
+ * Floating point constants are a sequence of digits, followed by a
+ decimal point, followed by a sequence of digits, and optionally
+ followed by an exponent. An exponent is of the form:
+ `e[[+]|-]NNN', where NNN is another sequence of digits. The `+'
+ is optional for positive exponents.
+
+ * Enumerated constants consist of enumerated identifiers, or their
+ integral equivalents.
+
+ * Character constants are a single character surrounded by single
+ quotes (`''), or a number--the ordinal value of the corresponding
+ character (usually its ASCII value). Within quotes, the single
+ character may be represented by a letter or by "escape sequences",
+ which are of the form `\NNN', where NNN is the octal representation
+ of the character's ordinal value; or of the form `\X', where `X'
+ is a predefined special character--for example, `\n' for newline.
+
+ * String constants are a sequence of character constants surrounded
+ by double quotes (`"').
+
+ * Pointer constants are an integral value. You can also write
+ pointers to constants using the C operator `&'.
+
+ * Array constants are comma-separated lists surrounded by braces `{'
+ and `}'; for example, `{1,2,3}' is a three-element array of
+ integers, `{{1,2}, {3,4}, {5,6}}' is a three-by-two array, and
+ `{&"hi", &"there", &"fred"}' is a three-element array of pointers.
+
+
+File: gdb.info, Node: Cplus expressions, Next: C Defaults, Prev: C Constants, Up: C
+
+C++ expressions
+---------------
+
+ GDB expression handling has a number of extensions to interpret a
+significant subset of C++ expressions.
+
+ *Warning:* Most of these extensions depend on the use of additional
+ debugging information in the symbol table, and thus require a rich,
+ extendable object code format. In particular, if your system uses
+ a.out, MIPS ECOFF, RS/6000 XCOFF, or Sun ELF with stabs extensions
+ to the symbol table, these facilities are all available. Where
+ the object code format is standard COFF, on the other hand, most
+ of the C++ support in GDB will *not* work, nor can it. For the
+ standard SVr4 debugging format, DWARF in ELF, the standard is
+ still evolving, so the C++ support in GDB is still fragile; when
+ this debugging format stabilizes, however, C++ support will also
+ be available on systems that use it.
+
+ 1. Member function calls are allowed; you can use expressions like
+
+ count = aml->GetOriginal(x, y)
+
+ 2. While a member function is active (in the selected stack frame),
+ your expressions have the same namespace available as the member
+ function; that is, GDB allows implicit references to the class
+ instance pointer `this' following the same rules as C++.
+
+ 3. You can call overloaded functions; GDB will resolve the function
+ call to the right definition, with one restriction--you must use
+ arguments of the type required by the function that you want to
+ call. GDB will not perform conversions requiring constructors or
+ user-defined type operators.
+
+ 4. GDB understands variables declared as C++ references; you can use
+ them in expressions just as you do in C++ source--they are
+ automatically dereferenced.
+
+ In the parameter list shown when GDB displays a frame, the values
+ of reference variables are not displayed (unlike other variables);
+ this avoids clutter, since references are often used for large
+ structures. The *address* of a reference variable is always
+ shown, unless you have specified `set print address off'.
+
+ 5. GDB supports the C++ name resolution operator `::'--your
+ expressions can use it just as expressions in your program do.
+ Since one scope may be defined in another, you can use `::'
+ repeatedly if necessary, for example in an expression like
+ `SCOPE1::SCOPE2::NAME'. GDB also allows resolving name scope by
+ reference to source files, in both C and C++ debugging (*note
+ Program variables: Variables.).
+
+
+File: gdb.info, Node: C Defaults, Next: C Checks, Prev: Cplus expressions, Up: C
+
+C and C++ defaults
+------------------
+
+ If you allow GDB to set type and range checking automatically, they
+both default to `off' whenever the working language changes to C or
+C++. This happens regardless of whether you, or GDB, selected the
+working language.
+
+ If you allow GDB to set the language automatically, it sets the
+working language to C or C++ on entering code compiled from a source
+file whose name ends with `.c', `.C', or `.cc'. *Note Having GDB infer
+the source language: Automatically, for further details.
+
+
+File: gdb.info, Node: C Checks, Next: Debugging C, Prev: C Defaults, Up: C
+
+C and C++ type and range checks
+-------------------------------
+
+ By default, when GDB parses C or C++ expressions, type checking is
+not used. However, if you turn type checking on, GDB will consider two
+variables type equivalent if:
+
+ * The two variables are structured and have the same structure,
+ union, or enumerated tag.
+
+ * Two two variables have the same type name, or types that have been
+ declared equivalent through `typedef'.
+
+ Range checking, if turned on, is done on mathematical operations.
+Array indices are not checked, since they are often used to index a
+pointer that is not itself an array.
+
+
+File: gdb.info, Node: Debugging C, Next: Debugging C plus plus, Prev: C Checks, Up: C
+
+GDB and C
+---------
+
+ The `set print union' and `show print union' commands apply to the
+`union' type. When set to `on', any `union' that is inside a `struct'
+or `class' will also be printed. Otherwise, it will appear as `{...}'.
+
+ The `@' operator aids in the debugging of dynamic arrays, formed
+with pointers and a memory allocation function. *Note Expressions:
+Expressions.
+
+
+File: gdb.info, Node: Debugging C plus plus, Prev: Debugging C, Up: C
+
+GDB features for C++
+--------------------
+
+ Some GDB commands are particularly useful with C++, and some are
+designed specifically for use with C++. Here is a summary:
+
+`breakpoint menus'
+ When you want a breakpoint in a function whose name is overloaded,
+ GDB breakpoint menus help you specify which function definition
+ you want. *Note Breakpoint menus: Breakpoint Menus.
+
+`rbreak REGEX'
+ Setting breakpoints using regular expressions is helpful for
+ setting breakpoints on overloaded functions that are not members
+ of any special classes. *Note Setting breakpoints: Set Breaks.
+
+`catch EXCEPTIONS'
+`info catch'
+ Debug C++ exception handling using these commands. *Note
+ Breakpoints and exceptions: Exception Handling.
+
+`ptype TYPENAME'
+ Print inheritance relationships as well as other information for
+ type TYPENAME. *Note Examining the Symbol Table: Symbols.
+
+`set print demangle'
+`show print demangle'
+`set print asm-demangle'
+`show print asm-demangle'
+ Control whether C++ symbols display in their source form, both when
+ displaying code as C++ source and when displaying disassemblies.
+ *Note Print settings: Print Settings.
+
+`set print object'
+`show print object'
+ Choose whether to print derived (actual) or declared types of
+ objects. *Note Print settings: Print Settings.
+
+`set print vtbl'
+`show print vtbl'
+ Control the format for printing virtual function tables. *Note
+ Print settings: Print Settings.
+
+`Overloaded symbol names'
+ You can specify a particular definition of an overloaded symbol,
+ using the same notation that is used to declare such symbols in
+ C++: type `SYMBOL(TYPES)' rather than just SYMBOL. You can also
+ use the GDB command-line word completion facilities to list the
+ available choices, or to finish the type list for you. *Note
+ Command completion: Completion, for details on how to do this.
+
+
+File: gdb.info, Node: Modula-2, Prev: C, Up: Support
+
+Modula-2
+--------
+
+ The extensions made to GDB to support Modula-2 only support output
+from the GNU Modula-2 compiler (which is currently being developed).
+Other Modula-2 compilers are not currently supported, and attempting to
+debug executables produced by them will most likely result in an error
+as GDB reads in the executable's symbol table.
+
+* Menu:
+
+* M2 Operators:: Built-in operators
+* Built-In Func/Proc:: Built-in functions and procedures
+* M2 Constants:: Modula-2 constants
+* M2 Defaults:: Default settings for Modula-2
+* Deviations:: Deviations from standard Modula-2
+* M2 Checks:: Modula-2 type and range checks
+* M2 Scope:: The scope operators `::' and `.'
+* GDB/M2:: GDB and Modula-2
+
+
+File: gdb.info, Node: M2 Operators, Next: Built-In Func/Proc, Up: Modula-2
+
+Operators
+---------
+
+ Operators must be defined on values of specific types. For instance,
+`+' is defined on numbers, but not on structures. Operators are often
+defined on groups of types. For the purposes of Modula-2, the
+following definitions hold:
+
+ * *Integral types* consist of `INTEGER', `CARDINAL', and their
+ subranges.
+
+ * *Character types* consist of `CHAR' and its subranges.
+
+ * *Floating-point types* consist of `REAL'.
+
+ * *Pointer types* consist of anything declared as `POINTER TO TYPE'.
+
+ * *Scalar types* consist of all of the above.
+
+ * *Set types* consist of `SET' and `BITSET' types.
+
+ * *Boolean types* consist of `BOOLEAN'.
+
+The following operators are supported, and appear in order of
+increasing precedence:
+
+`,'
+ Function argument or array index separator.
+
+`:='
+ Assignment. The value of VAR `:=' VALUE is VALUE.
+
+`<, >'
+ Less than, greater than on integral, floating-point, or enumerated
+ types.
+
+`<=, >='
+ Less than, greater than, less than or equal to, greater than or
+ equal to on integral, floating-point and enumerated types, or set
+ inclusion on set types. Same precedence as `<'.
+
+`=, <>, #'
+ Equality and two ways of expressing inequality, valid on scalar
+ types. Same precedence as `<'. In GDB scripts, only `<>' is
+ available for inequality, since `#' conflicts with the script
+ comment character.
+
+`IN'
+ Set membership. Defined on set types and the types of their
+ members. Same precedence as `<'.
+
+`OR'
+ Boolean disjunction. Defined on boolean types.
+
+`AND, &'
+ Boolean conjuction. Defined on boolean types.
+
+`@'
+ The GDB "artificial array" operator (*note Expressions:
+ Expressions.).
+
+`+, -'
+ Addition and subtraction on integral and floating-point types, or
+ union and difference on set types.
+
+`*'
+ Multiplication on integral and floating-point types, or set
+ intersection on set types.
+
+`/'
+ Division on floating-point types, or symmetric set difference on
+ set types. Same precedence as `*'.
+
+`DIV, MOD'
+ Integer division and remainder. Defined on integral types. Same
+ precedence as `*'.
+
+`-'
+ Negative. Defined on `INTEGER' and `REAL' data.
+
+`^'
+ Pointer dereferencing. Defined on pointer types.
+
+`NOT'
+ Boolean negation. Defined on boolean types. Same precedence as
+ `^'.
+
+`.'
+ `RECORD' field selector. Defined on `RECORD' data. Same
+ precedence as `^'.
+
+`[]'
+ Array indexing. Defined on `ARRAY' data. Same precedence as `^'.
+
+`()'
+ Procedure argument list. Defined on `PROCEDURE' objects. Same
+ precedence as `^'.
+
+`::, .'
+ GDB and Modula-2 scope operators.
+
+ *Warning:* Sets and their operations are not yet supported, so GDB
+ will treat the use of the operator `IN', or the use of operators
+ `+', `-', `*', `/', `=', , `<>', `#', `<=', and `>=' on sets as an
+ error.
+
+
+File: gdb.info, Node: Built-In Func/Proc, Next: M2 Constants, Prev: M2 Operators, Up: Modula-2
+
+Built-in functions and procedures
+---------------------------------
+
+ Modula-2 also makes available several built-in procedures and
+functions. In describing these, the following metavariables are used:
+
+A
+ represents an `ARRAY' variable.
+
+C
+ represents a `CHAR' constant or variable.
+
+I
+ represents a variable or constant of integral type.
+
+M
+ represents an identifier that belongs to a set. Generally used in
+ the same function with the metavariable S. The type of S should
+ be `SET OF MTYPE' (where MTYPE is the type of M).
+
+N
+ represents a variable or constant of integral or floating-point
+ type.
+
+R
+ represents a variable or constant of floating-point type.
+
+T
+ represents a type.
+
+V
+ represents a variable.
+
+X
+ represents a variable or constant of one of many types. See the
+ explanation of the function for details.
+
+ All Modula-2 built-in procedures also return a result, described
+below.
+
+`ABS(N)'
+ Returns the absolute value of N.
+
+`CAP(C)'
+ If C is a lower case letter, it returns its upper case equivalent,
+ otherwise it returns its argument
+
+`CHR(I)'
+ Returns the character whose ordinal value is I.
+
+`DEC(V)'
+ Decrements the value in the variable V. Returns the new value.
+
+`DEC(V,I)'
+ Decrements the value in the variable V by I. Returns the new
+ value.
+
+`EXCL(M,S)'
+ Removes the element M from the set S. Returns the new set.
+
+`FLOAT(I)'
+ Returns the floating point equivalent of the integer I.
+
+`HIGH(A)'
+ Returns the index of the last member of A.
+
+`INC(V)'
+ Increments the value in the variable V. Returns the new value.
+
+`INC(V,I)'
+ Increments the value in the variable V by I. Returns the new
+ value.
+
+`INCL(M,S)'
+ Adds the element M to the set S if it is not already there.
+ Returns the new set.
+
+`MAX(T)'
+ Returns the maximum value of the type T.
+
+`MIN(T)'
+ Returns the minimum value of the type T.
+
+`ODD(I)'
+ Returns boolean TRUE if I is an odd number.
+
+`ORD(X)'
+ Returns the ordinal value of its argument. For example, the
+ ordinal value of a character is its ASCII value (on machines
+ supporting the ASCII character set). X must be of an ordered
+ type, which include integral, character and enumerated types.
+
+`SIZE(X)'
+ Returns the size of its argument. X can be a variable or a type.
+
+`TRUNC(R)'
+ Returns the integral part of R.
+
+`VAL(T,I)'
+ Returns the member of the type T whose ordinal value is I.
+
+ *Warning:* Sets and their operations are not yet supported, so
+ GDB will treat the use of procedures `INCL' and `EXCL' as an error.
+
+
+File: gdb.info, Node: M2 Constants, Next: M2 Defaults, Prev: Built-In Func/Proc, Up: Modula-2
+
+Constants
+---------
+
+ GDB allows you to express the constants of Modula-2 in the following
+ways:
+
+ * Integer constants are simply a sequence of digits. When used in an
+ expression, a constant is interpreted to be type-compatible with
+ the rest of the expression. Hexadecimal integers are specified by
+ a trailing `H', and octal integers by a trailing `B'.
+
+ * Floating point constants appear as a sequence of digits, followed
+ by a decimal point and another sequence of digits. An optional
+ exponent can then be specified, in the form `E[+|-]NNN', where
+ `[+|-]NNN' is the desired exponent. All of the digits of the
+ floating point constant must be valid decimal (base 10) digits.
+
+ * Character constants consist of a single character enclosed by a
+ pair of like quotes, either single (`'') or double (`"'). They may
+ also be expressed by their ordinal value (their ASCII value,
+ usually) followed by a `C'.
+
+ * String constants consist of a sequence of characters enclosed by a
+ pair of like quotes, either single (`'') or double (`"'). Escape
+ sequences in the style of C are also allowed. *Note C and C++
+ constants: C Constants, for a brief explanation of escape
+ sequences.
+
+ * Enumerated constants consist of an enumerated identifier.
+
+ * Boolean constants consist of the identifiers `TRUE' and `FALSE'.
+
+ * Pointer constants consist of integral values only.
+
+ * Set constants are not yet supported.
+
+
+File: gdb.info, Node: M2 Defaults, Next: Deviations, Prev: M2 Constants, Up: Modula-2
+
+Modula-2 defaults
+-----------------
+
+ If type and range checking are set automatically by GDB, they both
+default to `on' whenever the working language changes to Modula-2.
+This happens regardless of whether you, or GDB, selected the working
+language.
+
+ If you allow GDB to set the language automatically, then entering
+code compiled from a file whose name ends with `.mod' will set the
+working language to Modula-2. *Note Having GDB set the language
+automatically: Automatically, for further details.
+
+
+File: gdb.info, Node: Deviations, Next: M2 Checks, Prev: M2 Defaults, Up: Modula-2
+
+Deviations from standard Modula-2
+---------------------------------
+
+ A few changes have been made to make Modula-2 programs easier to
+debug. This is done primarily via loosening its type strictness:
+
+ * Unlike in standard Modula-2, pointer constants can be formed by
+ integers. This allows you to modify pointer variables during
+ debugging. (In standard Modula-2, the actual address contained in
+ a pointer variable is hidden from you; it can only be modified
+ through direct assignment to another pointer variable or
+ expression that returned a pointer.)
+
+ * C escape sequences can be used in strings and characters to
+ represent non-printable characters. GDB will print out strings
+ with these escape sequences embedded. Single non-printable
+ characters are printed using the `CHR(NNN)' format.
+
+ * The assignment operator (`:=') returns the value of its right-hand
+ argument.
+
+ * All built-in procedures both modify *and* return their argument.
+
+
+File: gdb.info, Node: M2 Checks, Next: M2 Scope, Prev: Deviations, Up: Modula-2
+
+Modula-2 type and range checks
+------------------------------
+
+ *Warning:* in this release, GDB does not yet perform type or range
+ checking.
+
+ GDB considers two Modula-2 variables type equivalent if:
+
+ * They are of types that have been declared equivalent via a `TYPE
+ T1 = T2' statement
+
+ * They have been declared on the same line. (Note: This is true of
+ the GNU Modula-2 compiler, but it may not be true of other
+ compilers.)
+
+ As long as type checking is enabled, any attempt to combine variables
+whose types are not equivalent is an error.
+
+ Range checking is done on all mathematical operations, assignment,
+array index bounds, and all built-in functions and procedures.
+
+
+File: gdb.info, Node: M2 Scope, Next: GDB/M2, Prev: M2 Checks, Up: Modula-2
+
+The scope operators `::' and `.'
+--------------------------------
+
+ There are a few subtle differences between the Modula-2 scope
+operator (`.') and the GDB scope operator (`::'). The two have similar
+syntax:
+
+
+ MODULE . ID
+ SCOPE :: ID
+
+where SCOPE is the name of a module or a procedure, MODULE the name of
+a module, and ID is any declared identifier within your program, except
+another module.
+
+ Using the `::' operator makes GDB search the scope specified by
+SCOPE for the identifier ID. If it is not found in the specified
+scope, then GDB will search all scopes enclosing the one specified by
+SCOPE.
+
+ Using the `.' operator makes GDB search the current scope for the
+identifier specified by ID that was imported from the definition module
+specified by MODULE. With this operator, it is an error if the
+identifier ID was not imported from definition module MODULE, or if ID
+is not an identifier in MODULE.
+
+
+File: gdb.info, Node: GDB/M2, Prev: M2 Scope, Up: Modula-2
+
+GDB and Modula-2
+----------------
+
+ Some GDB commands have little use when debugging Modula-2 programs.
+Five subcommands of `set print' and `show print' apply specifically to
+C and C++: `vtbl', `demangle', `asm-demangle', `object', and `union'.
+The first four apply to C++, and the last to the C `union' type, which
+has no direct analogue in Modula-2.
+
+ The `@' operator (*note Expressions: Expressions.), while available
+while using any language, is not useful with Modula-2. Its intent is
+to aid the debugging of "dynamic arrays", which cannot be created in
+Modula-2 as they can in C or C++. However, because an address can be
+specified by an integral constant, the construct `{TYPE}ADREXP' is
+still useful. (*note Expressions: Expressions.)
+
+ In GDB scripts, the Modula-2 inequality operator `#' is interpreted
+as the beginning of a comment. Use `<>' instead.
+
+
+File: gdb.info, Node: Symbols, Next: Altering, Prev: Languages, Up: Top
+
+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 inherent in the text of your program and
+does not change as your program executes. GDB finds it in your
+program's symbol table, in the file indicated when you started GDB
+(*note Choosing files: File Options.), or by one of the file-management
+commands (*note Commands to specify files: Files.).
+
+ Occasionally, you may need to refer to symbols that contain unusual
+characters, which GDB ordinarily treats as word delimiters. The most
+frequent case is in referring to static variables in other source files
+(*note Program variables: Variables.). File names are recorded in
+object files as debugging symbols, but GDB would ordinarily parse a
+typical file name, like `foo.c', as the three words `foo' `.' `c'. To
+allow GDB to recognize `foo.c' as a single symbol, enclose it in single
+quotes; for example,
+
+ p 'foo.c'::x
+
+looks up the value of `x' in the scope of the file `foo.c'.
+
+`info address SYMBOL'
+ Describe where the data for 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 `print &SYMBOL', which does not work at all
+ for a register variable, and for a stack local variable prints the
+ exact address of the current instantiation of the variable.
+
+`whatis EXP'
+ Print the data type of expression EXP. EXP is not actually
+ evaluated, and any side-effecting operations (such as assignments
+ or function calls) inside it do not take place. *Note
+ Expressions: Expressions.
+
+`whatis'
+ Print the data type of `$', the last value in the value history.
+
+`ptype TYPENAME'
+ Print a description of data type TYPENAME. TYPENAME may be the
+ name of a type, or for C code it may have the form `class
+ CLASS-NAME', `struct STRUCT-TAG', `union UNION-TAG' or `enum
+ ENUM-TAG'.
+
+`ptype EXP'
+`ptype'
+ Print a description of the type of expression EXP. `ptype'
+ differs from `whatis' by printing a detailed description, instead
+ of just the name of the type.
+
+ For example, for this variable declaration:
+
+ struct complex {double real; double imag;} v;
+
+ the two commands give this output:
+
+ (gdb) whatis v
+ type = struct complex
+ (gdb) ptype v
+ type = struct complex {
+ double real;
+ double imag;
+ }
+
+ As with `whatis', using `ptype' without an argument refers to the
+ type of `$', the last value in the value history.
+
+`info types REGEXP'
+`info types'
+ Print a brief description of all types whose name matches REGEXP
+ (or all types in your program, if you supply no argument). Each
+ complete typename is matched as though it were a complete line;
+ thus, `i type value' gives information on all types in your
+ program whose name includes the string `value', but `i type
+ ^value$' gives information only on types whose complete name is
+ `value'.
+
+ This command differs from `ptype' in two ways: first, like
+ `whatis', it does not print a detailed description; second, it
+ lists all source files where a type is defined.
+
+`info source'
+ Show the name of the current source file--that is, the source file
+ for the function containing the current point of execution--and
+ the language it was written in.
+
+`info sources'
+ Print the names of all source files in your program for which
+ there is debugging information, organized into two lists: files
+ whose symbols have already been read, and files whose symbols will
+ be read when needed.
+
+`info functions'
+ Print the names and data types of all defined functions.
+
+`info functions REGEXP'
+ Print the names and data types of all defined functions whose
+ names contain a match for regular expression REGEXP. Thus, `info
+ fun step' finds all functions whose names include `step'; `info
+ fun ^step' finds those whose names start with `step'.
+
+`info variables'
+ Print the names and data types of all variables that are declared
+ outside of functions (i.e., excluding local variables).
+
+`info variables REGEXP'
+ Print the names and data types of all variables (except for local
+ variables) whose names contain a match for regular expression
+ REGEXP.
+
+`maint print symbols FILENAME'
+`maint print psymbols FILENAME'
+`maint print msymbols FILENAME'
+ Write a dump of debugging symbol data into the file FILENAME.
+ These commands are used to debug the GDB symbol-reading code. Only
+ symbols with debugging data are included. If you use `maint print
+ symbols', GDB includes all the symbols for which it has already
+ collected full details: that is, FILENAME reflects symbols for
+ only those files whose symbols GDB has read. You can use the
+ command `info sources' to find out which files these are. If you
+ use `maint print psymbols' instead, the dump shows information
+ about symbols that GDB only knows partially--that is, symbols
+ defined in files that GDB has skimmed, but not yet read
+ completely. Finally, `maint print msymbols' dumps just the
+ minimal symbol information required for each object file from
+ which GDB has read some symbols. *Note Commands to specify files:
+ Files, for a discussion of how GDB reads symbols (in the
+ description of `symbol-file').
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.info-5 b/gnu/usr.bin/gdb/doc/gdb.info-5
new file mode 100644
index 000000000000..ecf3d18b96f5
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info-5
@@ -0,0 +1,1215 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+File: gdb.info, Node: Altering, Next: GDB Files, Prev: Symbols, Up: Top
+
+Altering Execution
+******************
+
+ Once you think you have found an error in your 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 GDB features for altering execution of
+the program.
+
+ For example, you can store new values into variables or memory
+locations, give your program a signal, restart it at a different
+address, or even return prematurely from a function to its caller.
+
+* Menu:
+
+* Assignment:: Assignment to variables
+* Jumping:: Continuing at a different address
+
+* Signaling:: Giving your program a signal
+
+* Returning:: Returning from a function
+* Calling:: Calling your program's functions
+* Patching:: Patching your program
+
+
+File: gdb.info, Node: Assignment, Next: Jumping, Up: Altering
+
+Assignment to variables
+=======================
+
+ To alter the value of a variable, evaluate an assignment expression.
+*Note Expressions: Expressions. For example,
+
+ print x=4
+
+stores the value 4 into the variable `x', and then prints the value of
+the assignment expression (which is 4). *Note Using GDB with Different
+Languages: Languages, for more information on operators in supported
+languages.
+
+ If you are not interested in seeing the value of the assignment, use
+the `set' command instead of the `print' command. `set' is really the
+same as `print' except that the expression's value is not printed and
+is not put in the value history (*note Value history: Value History.).
+The expression is evaluated only for its effects.
+
+ If the beginning of the argument string of the `set' command appears
+identical to a `set' subcommand, use the `set variable' command instead
+of just `set'. This command is identical to `set' except for its lack
+of subcommands. For example, if your program has a variable `width',
+you get an error if you try to set a new value with just `set width=13',
+because GDB has the command `set width':
+
+ (gdb) whatis width
+ type = double
+ (gdb) p width
+ $4 = 13
+ (gdb) set width=47
+ Invalid syntax in expression.
+
+The invalid expression, of course, is `=47'. In order to actually set
+the program's variable `width', use
+
+ (gdb) set var width=47
+
+ GDB allows more implicit conversions in assignments than C; you can
+freely store an integer value into a pointer variable or vice versa,
+and you can convert any structure to any other structure that is the
+same length or shorter.
+
+ To store values into arbitrary places in memory, use the `{...}'
+construct to generate a value of specified type at a specified address
+(*note Expressions: Expressions.). For example, `{int}0x83040' refers
+to memory location `0x83040' as an integer (which implies a certain size
+and representation in memory), and
+
+ set {int}0x83040 = 4
+
+stores the value 4 into that memory location.
+
+
+File: gdb.info, Node: Jumping, Next: Signaling, Prev: Assignment, Up: Altering
+
+Continuing at a different address
+=================================
+
+ Ordinarily, when you continue your program, you do so at the place
+where it stopped, with the `continue' command. You can instead
+continue at an address of your own choosing, with the following
+commands:
+
+`jump LINESPEC'
+ Resume execution at line LINESPEC. Execution will stop
+ immediately if there is a breakpoint there. *Note Printing source
+ lines: List, for a description of the different forms of LINESPEC.
+
+ The `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 LINESPEC 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 `jump'
+ command requests confirmation if the specified line is not in the
+ function currently executing. However, even bizarre results are
+ predictable if you are well acquainted with the machine-language
+ code of your program.
+
+`jump *ADDRESS'
+ Resume execution at the instruction at address ADDRESS.
+
+ You can get much the same effect as the `jump' command by storing a
+new value into the register `$pc'. The difference is that this does
+not start your program running; it only changes the address where it
+*will* run when it is continued. For example,
+
+ set $pc = 0x485
+
+causes the next `continue' command or stepping command to execute at
+address `0x485', rather than at the address where your program stopped.
+*Note Continuing and stepping: Continuing and Stepping.
+
+ The most common occasion to use the `jump' command is to back up,
+perhaps with more breakpoints set, over a portion of a program that has
+already executed, in order to examine its execution in more detail.
+
+
+File: gdb.info, Node: Signaling, Next: Returning, Prev: Jumping, Up: Altering
+
+Giving your program a signal
+============================
+
+`signal SIGNAL'
+ Resume execution where your program stopped, but immediately give
+ it the signal SIGNAL. SIGNAL can be the name or the number of a
+ signal. For example, on many systems `signal 2' and `signal
+ SIGINT' are both ways of sending an interrupt signal.
+
+ Alternatively, if SIGNAL is zero, continue execution without
+ giving a signal. This is useful when your program stopped on
+ account of a signal and would ordinary see the signal when resumed
+ with the `continue' command; `signal 0' causes it to resume
+ without a signal.
+
+ `signal' does not repeat when you press RET a second time after
+ executing the command.
+
+ Invoking the `signal' command is not the same as invoking the `kill'
+utility from the shell. Sending a signal with `kill' causes GDB to
+decide what to do with the signal depending on the signal handling
+tables (*note Signals::.). The `signal' command passes the signal
+directly to your program.
+
+
+File: gdb.info, Node: Returning, Next: Calling, Prev: Signaling, Up: Altering
+
+Returning from a function
+=========================
+
+`return'
+`return EXPRESSION'
+ You can cancel execution of a function call with the `return'
+ command. If you give an EXPRESSION argument, its value is used as
+ the function's return value.
+
+ When you use `return', GDB 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 `return'.
+
+ This pops the selected stack frame (*note Selecting a frame:
+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 `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 `finish' command (*note Continuing and
+stepping: Continuing and Stepping.) resumes execution until the
+selected stack frame returns naturally.
+
+
+File: gdb.info, Node: Calling, Next: Patching, Prev: Returning, Up: Altering
+
+Calling program functions
+=========================
+
+`call EXPR'
+ Evaluate the expression EXPR without displaying `void' returned
+ values.
+
+ You can use this variant of the `print' command if you want to
+execute a function from your program, but without cluttering the output
+with `void' returned values. The result is printed and saved in the
+value history, if it is not void.
+
+
+File: gdb.info, Node: Patching, Prev: Calling, Up: Altering
+
+Patching programs
+=================
+
+ By default, GDB opens the file containing your program's executable
+code (or the corefile) read-only. This prevents accidental alterations
+to machine code; but it also prevents you from intentionally patching
+your program's binary.
+
+ If you'd like to be able to patch the binary, you can specify that
+explicitly with the `set write' command. For example, you might want
+to turn on internal debugging flags, or even to make emergency repairs.
+
+`set write on'
+`set write off'
+ If you specify `set write on', GDB will open executable and core
+ files for both reading and writing; if you specify `set write off'
+ (the default), GDB will open them read-only.
+
+ If you have already loaded a file, you must load it again (using
+ the `exec-file' or `core-file' command) after changing `set
+ write', for your new setting to take effect.
+
+`show write'
+ Display whether executable files and core files will be opened for
+ writing as well as reading.
+
+
+File: gdb.info, Node: GDB Files, Next: Targets, Prev: Altering, Up: Top
+
+GDB Files
+*********
+
+ GDB 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 your program.
+To debug a core dump of a previous run, you must also tell GDB the name
+of the core dump file.
+
+* Menu:
+
+* Files:: Commands to specify files
+* Symbol Errors:: Errors reading symbol files
+
+
+File: gdb.info, Node: Files, Next: Symbol Errors, Up: GDB Files
+
+Commands to specify files
+=========================
+
+ The usual way to specify executable and core dump file names is with
+the command arguments given when you start GDB (*note Getting In and
+Out of GDB: Invocation..
+
+ Occasionally it is necessary to change to a different file during a
+GDB session. Or you may run GDB and forget to specify a file you want
+to use. In these situations the GDB commands to specify new files are
+useful.
+
+`file FILENAME'
+ Use 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 `run' command. If you do not
+ specify a directory and the file is not found in the GDB working
+ directory, GDB uses the environment variable `PATH' as a list of
+ directories to search, just as the shell does when looking for a
+ program to run. You can change the value of this variable, for
+ both GDB and your program, using the `path' command.
+
+ On systems with memory-mapped files, an auxiliary symbol table file
+ `FILENAME.syms' may be available for FILENAME. If it is, GDB will
+ map in the symbol table from `FILENAME.syms', starting up more
+ quickly. See the descriptions of the options `-mapped' and
+ `-readnow' (available on the command line, and with the commands
+ `file', `symbol-file', or `add-symbol-file'), for more information.
+
+`file'
+ `file' with no argument makes GDB discard any information it has
+ on both executable file and the symbol table.
+
+`exec-file [ FILENAME ]'
+ Specify that the program to be run (but not the symbol table) is
+ found in FILENAME. GDB will search the environment variable `PATH'
+ if necessary to locate your program. Omitting FILENAME means to
+ discard information on the executable file.
+
+`symbol-file [ FILENAME ]'
+ Read symbol table information from file FILENAME. `PATH' is
+ searched when necessary. Use the `file' command to get both symbol
+ table and program to run from the same file.
+
+ `symbol-file' with no argument clears out GDB information on your
+ program's symbol table.
+
+ The `symbol-file' command causes GDB 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
+ GDB.
+
+ `symbol-file' will not repeat if you press RET again after
+ executing it once.
+
+ When GDB 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 a GNU compiler,
+ or other compilers that adhere to the local conventions. Best
+ results are usually obtained from GNU compilers; for example,
+ using `gcc' you can generate debugging information for optimized
+ code.
+
+ On some kinds of object files, the `symbol-file' command does not
+ normally 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, as they are needed.
+
+ The purpose of this two-stage reading strategy is to make GDB
+ 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 `set verbose' command can turn
+ these pauses into messages if desired. *Note Optional warnings
+ and messages: Messages/Warnings.)
+
+ We have not implemented the two-stage strategy for COFF yet. When
+ the symbol table is stored in COFF format, `symbol-file' reads the
+ symbol table data in full right away.
+
+`symbol-file FILENAME [ -readnow ] [ -mapped ]'
+`file FILENAME [ -readnow ] [ -mapped ]'
+ You can override the GDB two-stage strategy for reading symbol
+ tables by using the `-readnow' option with any of the commands that
+ load symbol table information, if you want to be sure GDB has the
+ entire symbol table available.
+
+ If memory-mapped files are available on your system through the
+ `mmap' system call, you can use another option, `-mapped', to
+ cause GDB to write the symbols for your program into a reusable
+ file. Future GDB debugging sessions will map in symbol information
+ from this auxiliary symbol file (if the program has not changed),
+ rather than spending time reading the symbol table from the
+ executable program. Using the `-mapped' option has the same
+ effect as starting GDB with the `-mapped' command-line option.
+
+ You can use both options together, to make sure the auxiliary
+ symbol file has all the symbol information for your program.
+
+ The auxiliary symbol file for a program called MYPROG is called
+ `MYPROG.syms'. Once this file exists (so long as it is newer than
+ the corresponding executable), GDB will always attempt to use it
+ when you debug MYPROG; no special options or commands are needed.
+
+ The `.syms' file is specific to the host machine where you run
+ GDB. It holds an exact image of the internal GDB symbol table.
+ It cannot be shared across multiple host platforms.
+
+`core-file [ FILENAME ]'
+ 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; GDB
+ can access the executable file itself for other parts.
+
+ `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 GDB. So, if you have been running your 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
+ `kill' command (*note Killing the child process: Kill Process.).
+
+`load FILENAME'
+ Depending on what remote debugging facilities are configured into
+ GDB, the `load' command may be available. Where it exists, it is
+ meant to make FILENAME (an executable) available for debugging on
+ the remote system--by downloading, or dynamic linking, for example.
+ `load' also records the FILENAME symbol table in GDB, like the
+ `add-symbol-file' command.
+
+ If your GDB does not have a `load' command, attempting to execute
+ it gets the error message "`You can't do that when your target is
+ ...'"
+
+ The file is loaded at whatever address is specified in the
+ executable. For some object file formats, like a.out, the object
+ file format fixes the address and so it won't necessarily match
+ the address you gave to the linker.
+
+ On VxWorks, `load' will dynamically link FILENAME on the current
+ target system as well as adding its symbols in GDB.
+
+ With the Nindy interface to an Intel 960 board, `load' will
+ download FILENAME to the 960 as well as adding its symbols in GDB.
+
+ When you select remote debugging to a Hitachi SH, H8/300, or
+ H8/500 board (*note GDB and Hitachi Microprocessors: Hitachi
+ Remote.), the `load' command downloads your program to the Hitachi
+ board and also opens it as the current executable target for GDB
+ on your host (like the `file' command).
+
+ `load' will not repeat if you press RET again after using it.
+
+`add-symbol-file FILENAME ADDRESS'
+`add-symbol-file FILENAME ADDRESS [ -readnow ] [ -mapped ]'
+ The `add-symbol-file' command reads additional symbol table
+ information from the file FILENAME. You would use this command
+ when FILENAME has been dynamically loaded (by some other means)
+ into the program that is running. ADDRESS should be the memory
+ address at which the file has been loaded; GDB cannot figure this
+ out for itself. You can specify ADDRESS as an expression.
+
+ The symbol table of the file FILENAME is added to the symbol table
+ originally read with the `symbol-file' command. You can use the
+ `add-symbol-file' command any number of times; the new symbol data
+ thus read keeps adding to the old. To discard all old symbol data
+ instead, use the `symbol-file' command.
+
+ `add-symbol-file' will not repeat if you press RET after using it.
+
+ You can use the `-mapped' and `-readnow' options just as with the
+ `symbol-file' command, to change how GDB manages the symbol table
+ information for FILENAME.
+
+`info files'
+`info target'
+ `info files' and `info target' are synonymous; both print the
+ current target (*note Specifying a Debugging Target: Targets.),
+ including the names of the executable and core dump files
+ currently in use by GDB, and the files from which symbols were
+ loaded. The command `help targets' lists all possible targets
+ rather than current ones.
+
+ All file-specifying commands allow both absolute and relative file
+names as arguments. GDB always converts the file name to an absolute
+path name and remembers it that way.
+
+ GDB supports SunOS, SVR4, and IBM RS/6000 shared libraries. GDB
+automatically loads symbol definitions from shared libraries when you
+use the `run' command, or when you examine a core file. (Before you
+issue the `run' command, GDB will not understand references to a
+function in a shared library, however--unless you are debugging a core
+file).
+
+`info share'
+`info sharedlibrary'
+ Print the names of the shared libraries which are currently loaded.
+
+`sharedlibrary REGEX'
+`share REGEX'
+ This is an obsolescent command; you can use it to explicitly load
+ shared object library symbols for files matching a Unix regular
+ expression, but as with files loaded automatically, it will only
+ load shared libraries required by your program for a core file or
+ after typing `run'. If REGEX is omitted all shared libraries
+ required by your program are loaded.
+
+
+File: gdb.info, Node: Symbol Errors, Prev: Files, Up: GDB Files
+
+Errors reading symbol files
+===========================
+
+ While reading a symbol file, GDB will occasionally encounter
+problems, such as symbol types it does not recognize, or known bugs in
+compiler output. By default, GDB does not notify you of such problems,
+since they are relatively common and primarily of interest to people
+debugging compilers. If you are interested in seeing information about
+ill-constructed symbol tables, you can either ask GDB to print only one
+message about each such type of problem, no matter how many times the
+problem occurs; or you can ask GDB to print more messages, to see how
+many times the problems occur, with the `set complaints' command (*note
+Optional warnings and messages: Messages/Warnings.).
+
+ The messages currently printed, and their meanings, include:
+
+`inner block not inside outer block in 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.
+
+ GDB circumvents the problem by treating the inner block as if it
+ had the same scope as the outer block. In the error message,
+ SYMBOL may be shown as "`(don't know)'" if the outer block is not a
+ function.
+
+`block at 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.
+
+ GDB does not circumvent this problem, and will have trouble
+ locating symbols in the source file whose symbols it is reading.
+ (You can often determine what source file is affected by specifying
+ `set verbose on'. *Note Optional warnings and messages:
+ Messages/Warnings.)
+
+`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.
+
+ GDB circumvents the problem by treating the symbol scope block as
+ starting on the previous source line.
+
+`bad string table offset in symbol N'
+ Symbol number N contains a pointer into the string table which is
+ larger than the size of the string table.
+
+ GDB circumvents the problem by considering the symbol to have the
+ name `foo', which may cause other problems if many symbols end up
+ with this name.
+
+`unknown symbol type `0xNN''
+ The symbol information contains new data types that GDB does not
+ yet know how to read. `0xNN' is the symbol type of the
+ misunderstood information, in hexadecimal.
+
+ GDB circumvents the error by ignoring this symbol information.
+ This will usually allow your 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 `gdb' with
+ itself, breakpoint on `complain', then go up to the function
+ `read_dbx_symtab' and examine `*bufp' to see the symbol.
+
+`stub type has NULL name'
+ GDB could not find the full definition for a struct or class.
+
+`const/volatile indicator missing (ok if using g++ v1.x), got...'
+ The symbol information for a C++ member function is missing some
+ information that recent versions of the compiler should have output
+ for it.
+
+`info mismatch between compiler and debugger'
+ GDB could not parse a type specification output by the compiler.
+
+
+File: gdb.info, Node: Targets, Next: Controlling GDB, Prev: GDB Files, Up: Top
+
+Specifying a Debugging Target
+*****************************
+
+ A "target" is the execution environment occupied by your program.
+Often, GDB runs in the same host environment as your program; in that
+case, the debugging target is specified as a side effect when you use
+the `file' or `core' commands. When you need more flexibility--for
+example, running GDB on a physically separate host, or controlling a
+standalone system over a serial port or a realtime system over a TCP/IP
+connection--you can use the `target' command to specify one of the
+target types configured for GDB (*note Commands for managing targets:
+Target Commands.).
+
+* Menu:
+
+* Active Targets:: Active targets
+* Target Commands:: Commands for managing targets
+* Remote:: Remote debugging
+
+
+File: gdb.info, Node: Active Targets, Next: Target Commands, Up: Targets
+
+Active targets
+==============
+
+ There are three classes of targets: processes, core files, and
+executable files. GDB can work concurrently on up to three active
+targets, one in each class. This allows you to (for example) start a
+process and inspect its activity without abandoning your work on a core
+file.
+
+ For example, if you execute `gdb a.out', then the executable file
+`a.out' is the only active target. If you designate a core file as
+well--presumably from a prior run that crashed and coredumped--then GDB
+has two active targets and will use them in tandem, looking first in
+the corefile target, then in the executable file, to satisfy requests
+for memory addresses. (Typically, these two classes of target are
+complementary, since core files contain only a program's read-write
+memory--variables and so on--plus machine status, while executable
+files contain only the program text and initialized data.)
+
+ When you type `run', your executable file becomes an active process
+target as well. When a process target is active, all GDB commands
+requesting memory addresses refer to that target; addresses in an
+active core file or executable file target are obscured while the
+process target is active.
+
+ Use the `core-file' and `exec-file' commands to select a new core
+file or executable target (*note Commands to specify files: Files.).
+To specify as a target a process that is already running, use the
+`attach' command (*note Debugging an already-running process: Attach.).
+
+
+File: gdb.info, Node: Target Commands, Next: Remote, Prev: Active Targets, Up: Targets
+
+Commands for managing targets
+=============================
+
+`target TYPE PARAMETERS'
+ Connects the GDB host environment to a target machine or process.
+ A target is typically a protocol for talking to debugging
+ facilities. You use the argument TYPE to specify the type or
+ protocol of the target machine.
+
+ Further 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.
+
+ The `target' command will not repeat if you press RET again after
+ executing the command.
+
+`help target'
+ Displays the names of all targets available. To display targets
+ currently selected, use either `info target' or `info files'
+ (*note Commands to specify files: Files.).
+
+`help target NAME'
+ Describe a particular target, including any parameters necessary to
+ select it.
+
+ Here are some common targets (available, or not, depending on the GDB
+configuration):
+
+`target exec PROGRAM'
+ An executable file. `target exec PROGRAM' is the same as
+ `exec-file PROGRAM'.
+
+`target core FILENAME'
+ A core dump file. `target core FILENAME' is the same as
+ `core-file FILENAME'.
+
+`target remote DEV'
+ Remote serial target in GDB-specific protocol. The argument DEV
+ specifies what serial device to use for the connection (e.g.
+ `/dev/ttya'). *Note Remote debugging: Remote.
+
+`target sim'
+ CPU simulator. *Note Simulated CPU Target: Simulator.
+
+`target udi KEYWORD'
+ Remote AMD29K target, using the AMD UDI protocol. The KEYWORD
+ argument specifies which 29K board or simulator to use. *Note GDB
+ and the UDI protocol for AMD29K: UDI29K Remote.
+
+`target amd-eb DEV SPEED PROG'
+ Remote PC-resident AMD EB29K board, attached over serial lines.
+ dEV is the serial device, as for `target remote'; SPEED allows you
+ to specify the linespeed; and PROG is the name of the program to
+ be debugged, as it appears to DOS on the PC. *Note GDB with a
+ remote EB29K: EB29K Remote.
+
+`target hms'
+ A Hitachi SH, H8/300, or H8/500 board, attached via serial line to
+ your host. Use special commands `device' and `speed' to control
+ the serial line and the communications speed used. *Note GDB and
+ Hitachi Microprocessors: Hitachi Remote.
+
+`target nindy DEVICENAME'
+ An Intel 960 board controlled by a Nindy Monitor. DEVICENAME is
+ the name of the serial device to use for the connection, e.g.
+ `/dev/ttya'. *Note GDB with a remote i960 (Nindy): i960-Nindy
+ Remote.
+
+`target st2000 DEV SPEED'
+ A Tandem ST2000 phone switch, running Tandem's STDBUG protocol.
+ dEV is the name of the device attached to the ST2000 serial line;
+ SPEED is the communication line speed. The arguments are not used
+ if GDB is configured to connect to the ST2000 using TCP or Telnet.
+ *Note GDB with a Tandem ST2000: ST2000 Remote.
+
+`target vxworks MACHINENAME'
+ A VxWorks system, attached via TCP/IP. The argument MACHINENAME
+ is the target system's machine name or IP address. *Note GDB and
+ VxWorks: VxWorks Remote.
+
+ Different targets are available on different configurations of GDB;
+your configuration may have more or fewer targets.
+
+
+File: gdb.info, Node: Remote, Prev: Target Commands, Up: Targets
+
+Remote debugging
+================
+
+ If you are trying to debug a program running on a machine that
+cannot run GDB in the usual way, it is often useful to use remote
+debugging. For example, you might use remote debugging on an operating
+system kernel, or on a small system which does not have a general
+purpose operating system powerful enough to run a full-featured
+debugger.
+
+ Some configurations of GDB have special serial or TCP/IP interfaces
+to make this work with particular debugging targets. In addition, GDB
+comes with a generic serial protocol (specific to GDB, but not specific
+to any particular target system) which you can use if you write the
+remote stubs--the code that will run on the remote system to
+communicate with GDB.
+
+ Other remote targets may be available in your configuration of GDB;
+use `help targets' to list them.
+
+* Menu:
+
+
+* Remote Serial:: GDB remote serial protocol
+
+* i960-Nindy Remote:: GDB with a remote i960 (Nindy)
+
+* UDI29K Remote:: GDB and the UDI protocol for AMD29K
+* EB29K Remote:: GDB with a remote EB29K
+
+* VxWorks Remote:: GDB and VxWorks
+
+* ST2000 Remote:: GDB with a Tandem ST2000
+
+* Hitachi Remote:: GDB and Hitachi Microprocessors
+
+* MIPS Remote:: GDB and MIPS boards
+
+* Simulator:: Simulated CPU target
+
+
+File: gdb.info, Node: Remote Serial, Next: i960-Nindy Remote, Up: Remote
+
+The GDB remote serial protocol
+------------------------------
+
+ To debug a program running on another machine (the debugging
+"target" machine), you must first arrange for all the usual
+prerequisites for the program to run by itself. For example, for a C
+program, you need
+
+ 1. A startup routine to set up the C runtime environment; these
+ usually have a name like `crt0'. The startup routine may be
+ supplied by your hardware supplier, or you may have to write your
+ own.
+
+ 2. You probably need a C subroutine library to support your program's
+ subroutine calls, notably managing input and output.
+
+ 3. A way of getting your program to the other machine--for example, a
+ download program. These are often supplied by the hardware
+ manufacturer, but you may have to write your own from hardware
+ documentation.
+
+ The next step is to arrange for your program to use a serial port to
+communicate with the machine where GDB is running (the "host" machine).
+In general terms, the scheme looks like this:
+
+*On the host,*
+ GDB already understands how to use this protocol; when everything
+ else is set up, you can simply use the `target remote' command
+ (*note Specifying a Debugging Target: Targets.).
+
+*On the target,*
+ you must link with your program a few special-purpose subroutines
+ that implement the GDB remote serial protocol. The file
+ containing these subroutines is called a "debugging stub".
+
+ On certain remote targets, you can use an auxiliary program
+ `gdbserver' instead of linking a stub into your program. *Note
+ Using the `gdbserver' program: Server, for details.
+
+ The debugging stub is specific to the architecture of the remote
+machine; for example, use `sparc-stub.c' to debug programs on SPARC
+boards.
+
+ These working remote stubs are distributed with GDB:
+
+`sparc-stub.c'
+ For SPARC architectures.
+
+`m68k-stub.c'
+ For Motorola 680x0 architectures.
+
+`i386-stub.c'
+ For Intel 386 and compatible architectures.
+
+ The `README' file in the GDB distribution may list other recently
+added stubs.
+
+* Menu:
+
+* Stub Contents:: What the stub can do for you
+* Bootstrapping:: What you must do for the stub
+* Debug Session:: Putting it all together
+* Protocol:: Outline of the communication protocol
+
+* Server:: Using the `gdbserver' program
+
+
+File: gdb.info, Node: Stub Contents, Next: Bootstrapping, Up: Remote Serial
+
+What the stub can do for you
+----------------------------
+
+ The debugging stub for your architecture supplies these three
+subroutines:
+
+`set_debug_traps'
+ This routine arranges for `handle_exception' to run when your
+ program stops. You must call this subroutine explicitly near the
+ beginning of your program.
+
+`handle_exception'
+ This is the central workhorse, but your program never calls it
+ explicitly--the setup code arranges for `handle_exception' to run
+ when a trap is triggered.
+
+ `handle_exception' takes control when your program stops during
+ execution (for example, on a breakpoint), and mediates
+ communications with GDB on the host machine. This is where the
+ communications protocol is implemented; `handle_exception' acts as
+ the GDB representative on the target machine; it begins by sending
+ summary information on the state of your program, then continues
+ to execute, retrieving and transmitting any information GDB needs,
+ until you execute a GDB command that makes your program resume; at
+ that point, `handle_exception' returns control to your own code on
+ the target machine.
+
+`breakpoint'
+ Use this auxiliary subroutine to make your program contain a
+ breakpoint. Depending on the particular situation, this may be
+ the only way for GDB to get control. For instance, if your target
+ machine has some sort of interrupt button, you won't need to call
+ this; pressing the interrupt button will transfer control to
+ `handle_exception'--in effect, to GDB. On some machines, simply
+ receiving characters on the serial port may also trigger a trap;
+ again, in that situation, you don't need to call `breakpoint' from
+ your own program--simply running `target remote' from the host GDB
+ session will get control.
+
+ Call `breakpoint' if none of these is true, or if you simply want
+ to make certain your program stops at a predetermined point for the
+ start of your debugging session.
+
+
+File: gdb.info, Node: Bootstrapping, Next: Debug Session, Prev: Stub Contents, Up: Remote Serial
+
+What you must do for the stub
+-----------------------------
+
+ The debugging stubs that come with GDB are set up for a particular
+chip architecture, but they have no information about the rest of your
+debugging target machine. To allow the stub to work, you must supply
+these special low-level subroutines:
+
+`int getDebugChar()'
+ Write this subroutine to read a single character from the serial
+ port. It may be identical to `getchar' for your target system; a
+ different name is used to allow you to distinguish the two if you
+ wish.
+
+`void putDebugChar(int)'
+ Write this subroutine to write a single character to the serial
+ port. It may be identical to `putchar' for your target system; a
+ different name is used to allow you to distinguish the two if you
+ wish.
+
+`void exceptionHandler (int EXCEPTION_NUMBER, void *EXCEPTION_ADDRESS)'
+ Write this function to install EXCEPTION_ADDRESS in the exception
+ handling tables. You need to do this because the stub does not
+ have any way of knowing what the exception handling tables on your
+ target system are like (for example, the processor's table might
+ be in ROM, containing entries which point to a table in RAM).
+ eXCEPTION_NUMBER is the exception number which should be changed;
+ its meaning is architecture-dependent (for example, different
+ numbers might represent divide by zero, misaligned access, etc).
+ When this exception occurs, control should be transferred directly
+ to EXCEPTION_ADDRESS, and the processor state (stack, registers,
+ etc.) should be just as it is when a processor exception occurs.
+ So if you want to use a jump instruction to reach
+ EXCEPTION_ADDRESS, it should be a simple jump, not a jump to
+ subroutine.
+
+ For the 386, EXCEPTION_ADDRESS should be installed as an interrupt
+ gate so that interrupts are masked while the handler runs. The
+ gate should be at privilege level 0 (the most privileged level).
+ The SPARC and 68k stubs are able to mask interrupts themself
+ without help from `exceptionHandler'.
+
+`void flush_i_cache()'
+ Write this subroutine to flush the instruction cache, if any, on
+ your target machine. If there is no instruction cache, this
+ subroutine may be a no-op.
+
+ On target machines that have instruction caches, GDB requires this
+ function to make certain that the state of your program is stable.
+
+You must also make sure this library routine is available:
+
+`void *memset(void *, int, int)'
+ This is the standard library function `memset' that sets an area of
+ memory to a known value. If you have one of the free versions of
+ `libc.a', `memset' can be found there; otherwise, you must either
+ obtain it from your hardware manufacturer, or write your own.
+
+ If you do not use the GNU C compiler, you may need other standard
+library subroutines as well; this will vary from one stub to another,
+but in general the stubs are likely to use any of the common library
+subroutines which `gcc' generates as inline code.
+
+
+File: gdb.info, Node: Debug Session, Next: Protocol, Prev: Bootstrapping, Up: Remote Serial
+
+Putting it all together
+-----------------------
+
+ In summary, when your program is ready to debug, you must follow
+these steps.
+
+ 1. Make sure you have the supporting low-level routines (*note What
+ you must do for the stub: Bootstrapping.):
+ `getDebugChar', `putDebugChar',
+ `flush_i_cache', `memset', `exceptionHandler'.
+
+ 2. Insert these lines near the top of your program:
+
+ set_debug_traps();
+ breakpoint();
+
+ 3. For the 680x0 stub only, you need to provide a variable called
+ `exceptionHook'. Normally you just use
+
+ void (*exceptionHook)() = 0;
+
+ but if before calling `set_debug_traps', you set it to point to a
+ function in your program, that function is called when `GDB'
+ continues after stopping on a trap (for example, bus error). The
+ function indicated by `exceptionHook' is called with one
+ parameter: an `int' which is the exception number.
+
+ 4. Compile and link together: your program, the GDB debugging stub for
+ your target architecture, and the supporting subroutines.
+
+ 5. Make sure you have a serial connection between your target machine
+ and the GDB host, and identify the serial port used for this on
+ the host.
+
+ 6. Download your program to your target machine (or get it there by
+ whatever means the manufacturer provides), and start it.
+
+ 7. To start remote debugging, run GDB on the host machine, and specify
+ as an executable file the program that is running in the remote
+ machine. This tells GDB how to find your program's symbols and
+ the contents of its pure text.
+
+ Then establish communication using the `target remote' command.
+ Its argument specifies how to communicate with the target
+ machine--either via a devicename attached to a direct serial line,
+ or a TCP port (usually to a terminal server which in turn has a
+ serial line to the target). For example, to use a serial line
+ connected to the device named `/dev/ttyb':
+
+ target remote /dev/ttyb
+
+ To use a TCP connection, use an argument of the form `HOST:port'.
+ For example, to connect to port 2828 on a terminal server named
+ `manyfarms':
+
+ target remote manyfarms:2828
+
+ 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 `detach'
+command.
+
+ Whenever GDB is waiting for the remote program, if you type the
+interrupt character (often C-C), GDB attempts to stop the program.
+This may or may not succeed, depending in part on the hardware and the
+serial drivers the remote system uses. If you type the interrupt
+character once again, GDB displays this prompt:
+
+ Interrupted while waiting for the program.
+ Give up (and stop debugging it)? (y or n)
+
+ If you type `y', GDB abandons the remote debugging session. (If you
+decide you want to try again later, you can use `target remote' again
+to connect once more.) If you type `n', GDB goes back to waiting.
+
+
+File: gdb.info, Node: Protocol, Next: Server, Prev: Debug Session, Up: Remote Serial
+
+Outline of the communication protocol
+-------------------------------------
+
+ The stub files provided with GDB implement the target side of the
+communication protocol, and the GDB side is implemented in the GDB
+source file `remote.c'. Normally, you can simply allow these
+subroutines to communicate, and ignore the details. (If you're
+implementing your own stub file, you can still ignore the details: start
+with one of the existing stub files. `sparc-stub.c' is the best
+organized, and therefore the easiest to read.)
+
+ However, there may be occasions when you need to know something about
+the protocol--for example, if there is only one serial port to your
+target machine, you might want your program to do something special if
+it recognizes a packet meant for GDB.
+
+ All GDB commands and responses (other than acknowledgements, which
+are single characters) are sent as a packet which includes a checksum.
+A packet is introduced with the character `$', and ends with the
+character `#' followed by a two-digit checksum:
+
+ $PACKET INFO#CHECKSUM
+
+CHECKSUM is computed as the modulo 256 sum of the PACKET INFO
+characters.
+
+ When either the host or the target machine receives a packet, the
+first response expected is an acknowledgement: a single character,
+either `+' (to indicate the package was received correctly) or `-' (to
+request retransmission).
+
+ The host (GDB) sends commands, and the target (the debugging stub
+incorporated in your program) sends data in response. The target also
+sends data when your program stops.
+
+ Command packets are distinguished by their first character, which
+identifies the kind of command.
+
+ These are the commands currently supported:
+
+`g'
+ Requests the values of CPU registers.
+
+`G'
+ Sets the values of CPU registers.
+
+`mADDR,COUNT'
+ Read COUNT bytes at location ADDR.
+
+`MADDR,COUNT:...'
+ Write COUNT bytes at location ADDR.
+
+`c'
+`cADDR'
+ Resume execution at the current address (or at ADDR if supplied).
+
+`s'
+`sADDR'
+ Step the target program for one instruction, from either the
+ current program counter or from ADDR if supplied.
+
+`k'
+ Kill the target program.
+
+`?'
+ Report the most recent signal. To allow you to take advantage of
+ the GDB signal handling commands, one of the functions of the
+ debugging stub is to report CPU traps as the corresponding POSIX
+ signal values.
+
+ If you have trouble with the serial connection, you can use the
+command `set remotedebug'. This makes GDB report on all packets sent
+back and forth across the serial line to the remote machine. The
+packet-debugging information is printed on the GDB standard output
+stream. `set remotedebug off' turns it off, and `show remotedebug'
+will show you its current state.
+
+
+File: gdb.info, Node: Server, Prev: Protocol, Up: Remote Serial
+
+Using the `gdbserver' program
+-----------------------------
+
+ `gdbserver' is a control program for Unix-like systems, which allows
+you to connect your program with a remote GDB via `target remote'--but
+without linking in the usual debugging stub.
+
+ `gdbserver' is not a complete replacement for the debugging stubs,
+because it requires essentially the same operating-system facilities
+that GDB itself does. In fact, a system that can run `gdbserver' to
+connect to a remote GDB could also run GDBN locally! `gdbserver' is
+sometimes useful nevertheless, because it is a much smaller program
+than GDB itself. It is also easier to port than all of GDBN, so you
+may be able to get started more quickly on a new system by using
+`gdbserver'.
+
+ GDB and `gdbserver' communicate via either a serial line or a TCP
+connection, using the standard GDB remote serial protocol.
+
+*On the target,*
+ you need to have a copy of the program you want to debug.
+ `gdbserver' does not need your program's symbol table, so you can
+ strip the program if necessary to save space. GDB on the host
+ system does all the symbol handling.
+
+ To use the server, you must tell it how to communicate with {No
+ Value For "GDB"}; the name of your program; and the arguments for
+ your program. The syntax is:
+
+ target> gdbserver COMM PROGRAM [ ARGS ... ]
+
+ COMM is either a device name (to use a serial line) or a TCP
+ hostname and portnumber. For example, to debug emacs with the
+ argument `foo.txt' and communicate with GDB over the serial port
+ `/dev/com1':
+
+ target> gdbserver /dev/com1 emacs foo.txt
+
+ `gdbserver' waits passively for the host GDB to communicate with
+ it.
+
+ To use a TCP connection instead of a serial line:
+
+ target> gdbserver host:2345 emacs foo.txt
+
+ The only difference from the previous example is the first
+ argument, specifying that you are communicating with the host GDB
+ via TCP. The `host:2345' argument means that `gdbserver' is to
+ expect a TCP connection from machine `host' to local TCP port 2345.
+ (Currently, the `host' part is ignored.) You can choose any number
+ you want for the port number as long as it does not conflict with
+ any TCP ports already in use on the target system.(1) You must use
+ the same port number with the host GDB `target remote' command.
+
+*On the host,*
+ you need an unstripped copy of your program, since GDB needs
+ symbols and debugging information. Start up GDB as usual, using
+ the name of the local copy of your program as the first argument.
+ (You may also need the `--baud' option if the serial line is
+ running at anything other than 9600 bps.) After that, use `target
+ remote' to establish communications with `gdbserver'. Its
+ argument is either a device name (usually a serial device, like
+ `/dev/ttyb'), or a TCP port descriptof in the form `HOST:PORT'.
+ For example:
+
+ (gdb) target remote /dev/ttyb
+
+ communicates with the server via serial line `/dev/ttyb', and
+
+ (gdb) target remote the-target:2345
+
+ communicates via a TCP connection to port 2345 on host
+ `the-target'. For TCP connections, you must start up `gdbserver'
+ prior to using the `target remote' command. Otherwise you may get
+ an error whose text depends on the host system, but which usually
+ looks something like `Connection refused'.
+
+ ---------- Footnotes ----------
+
+ (1) If you choose a port number that conflicts with another
+service, `gdbserver' prints an error message and exits.
+
+
+File: gdb.info, Node: i960-Nindy Remote, Next: UDI29K Remote, Prev: Remote Serial, Up: Remote
+
+GDB with a remote i960 (Nindy)
+------------------------------
+
+ "Nindy" is a ROM Monitor program for Intel 960 target systems. When
+GDB is configured to control a remote Intel 960 using Nindy, you can
+tell GDB how to connect to the 960 in several ways:
+
+ * Through command line options specifying serial port, version of the
+ Nindy protocol, and communications speed;
+
+ * By responding to a prompt on startup;
+
+ * By using the `target' command at any point during your GDB
+ session. *Note Commands for managing targets: Target Commands.
+
+* Menu:
+
+* Nindy Startup:: Startup with Nindy
+* Nindy Options:: Options for Nindy
+* Nindy Reset:: Nindy reset command
+
+
+File: gdb.info, Node: Nindy Startup, Next: Nindy Options, Up: i960-Nindy Remote
+
+Startup with Nindy
+------------------
+
+ If you simply start `gdb' without using any command-line options,
+you are prompted for what serial port to use, *before* you reach the
+ordinary GDB prompt:
+
+ Attach /dev/ttyNN -- specify NN, or "quit" to quit:
+
+Respond to the prompt with whatever suffix (after `/dev/tty')
+identifies the serial port you want to use. 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 `target' (*note Commands for managing targets: Target Commands.).
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.info-6 b/gnu/usr.bin/gdb/doc/gdb.info-6
new file mode 100644
index 000000000000..8a746fd77b6d
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info-6
@@ -0,0 +1,1220 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+File: gdb.info, Node: Nindy Options, Next: Nindy Reset, Prev: Nindy Startup, Up: i960-Nindy Remote
+
+Options for Nindy
+-----------------
+
+ These are the startup options for beginning your GDB session with a
+Nindy-960 board attached:
+
+`-r 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
+ GDB is configured for the Intel 960 target architecture. You may
+ specify PORT as any of: a full pathname (e.g. `-r /dev/ttya'), a
+ device name in `/dev' (e.g. `-r ttya'), or simply the unique
+ suffix for a specific `tty' (e.g. `-r a').
+
+`-O'
+ (An uppercase letter "O", not a zero.) Specify that GDB should use
+ the "old" Nindy monitor protocol to connect to the target system.
+ This option is only available when GDB is configured for the Intel
+ 960 target architecture.
+
+ *Warning:* if you specify `-O', but are actually trying to
+ connect to a target system that expects the newer protocol,
+ the connection fails, appearing to be a speed mismatch. GDB
+ repeatedly attempts to reconnect at several different line
+ speeds. You can abort this process with an interrupt.
+
+`-brk'
+ Specify that GDB should first send a `BREAK' signal to the target
+ system, in an attempt to reset it, before connecting to a Nindy
+ target.
+
+ *Warning:* Many target systems do not have the hardware that
+ this requires; it only works with a few boards.
+
+ The standard `-b' option controls the line speed used on the serial
+port.
+
+
+File: gdb.info, Node: Nindy Reset, Prev: Nindy Options, Up: i960-Nindy Remote
+
+Nindy reset command
+-------------------
+
+`reset'
+ For a Nindy target, 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.
+
+
+File: gdb.info, Node: UDI29K Remote, Next: EB29K Remote, Prev: i960-Nindy Remote, Up: Remote
+
+GDB and the UDI protocol for AMD29K
+-----------------------------------
+
+ GDB supports AMD's UDI ("Universal Debugger Interface") protocol for
+debugging the a29k processor family. To use this configuration with
+AMD targets running the MiniMON monitor, you need the program `MONTIP',
+available from AMD at no charge. You can also use GDB with the UDI
+conformant a29k simulator program `ISSTIP', also available from AMD.
+
+`target udi KEYWORD'
+ Select the UDI interface to a remote a29k board or simulator, where
+ KEYWORD is an entry in the AMD configuration file `udi_soc'. This
+ file contains keyword entries which specify parameters used to
+ connect to a29k targets. If the `udi_soc' file is not in your
+ working directory, you must set the environment variable `UDICONF'
+ to its pathname.
+
+
+File: gdb.info, Node: EB29K Remote, Next: VxWorks Remote, Prev: UDI29K Remote, Up: Remote
+
+GDB and the EBMON protocol for AMD29K
+-------------------------------------
+
+ AMD distributes a 29K development board meant to fit in a PC,
+together with a DOS-hosted monitor program called `EBMON'. As a
+shorthand term, this development system is called the "EB29K". To use
+GDB from a Unix system to run programs on the EB29K board, you must
+first connect a serial cable between the PC (which hosts the EB29K
+board) and a serial port on the Unix system. In the following, we
+assume you've hooked the cable between the PC's `COM1' port and
+`/dev/ttya' on the Unix system.
+
+* Menu:
+
+* Comms (EB29K):: Communications setup
+* gdb-EB29K:: EB29K cross-debugging
+* Remote Log:: Remote log
+
+
+File: gdb.info, Node: Comms (EB29K), Next: gdb-EB29K, Up: EB29K Remote
+
+Communications setup
+--------------------
+
+ The next step is to set up the PC's port, by doing something like
+this in DOS on the PC:
+
+ C:\> MODE com1:9600,n,8,1,none
+
+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.
+
+ To give control of the PC to the Unix side of the serial line, type
+the following at the DOS console:
+
+ C:\> CTTY com1
+
+(Later, if you wish to return control to the DOS console, you can use
+the command `CTTY con'--but you must send it over the device that had
+control, in our example over the `COM1' serial line).
+
+ From the Unix host, use a communications program such as `tip' or
+`cu' to communicate with the PC; for example,
+
+ cu -s 9600 -l /dev/ttya
+
+The `cu' options shown specify, respectively, the linespeed and the
+serial port to use. If you use `tip' instead, your command line may
+look something like the following:
+
+ tip -9600 /dev/ttya
+
+Your system may require a different name where we show `/dev/ttya' as
+the argument to `tip'. The communications parameters, including which
+port to use, are associated with the `tip' argument in the "remote"
+descriptions file--normally the system table `/etc/remote'.
+
+ Using the `tip' or `cu' connection, change the DOS working directory
+to the directory containing a copy of your 29K program, then start the
+PC program `EBMON' (an EB29K control program supplied with your board
+by AMD). You should see an initial display from `EBMON' similar to the
+one that follows, ending with the `EBMON' prompt `#'--
+
+ 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
+
+ # ~.
+
+ Then exit the `cu' or `tip' program (done in the example by typing
+`~.' at the `EBMON' prompt). `EBMON' will keep running, ready for GDB
+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 `G:'" on the PC as
+a file system on the Unix host. If you do not 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; GDB will *not* download it over the serial line.
+
+
+File: gdb.info, Node: gdb-EB29K, Next: Remote Log, Prev: Comms (EB29K), Up: EB29K Remote
+
+EB29K cross-debugging
+---------------------
+
+ Finally, `cd' to the directory containing an image of your 29K
+program on the Unix system, and start GDB--specifying as argument the
+name of your 29K program:
+
+ cd /usr/joe/work29k
+ gdb myfoo
+
+ Now you can use the `target' command:
+
+ target amd-eb /dev/ttya 9600 MYFOO
+
+In this example, we've assumed your program is in a file called
+`myfoo'. Note that the filename given as the last argument to `target
+amd-eb' should be the name of the program as it appears to DOS. In our
+example this is simply `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 are
+ready to see your program run on the 29K board, use the GDB command
+`run'.
+
+ To stop debugging the remote program, use the GDB `detach' command.
+
+ To return control of the PC to its console, use `tip' or `cu' once
+again, after your GDB session has concluded, to attach to `EBMON'. You
+can then type the command `q' to shut down `EBMON', returning control
+to the DOS command-line interpreter. Type `CTTY con' to return command
+input to the main DOS console, and type `~.' to leave `tip' or `cu'.
+
+
+File: gdb.info, Node: Remote Log, Prev: gdb-EB29K, Up: EB29K Remote
+
+Remote log
+----------
+
+ The `target amd-eb' command creates a file `eb.log' in the current
+working directory, to help debug problems with the connection.
+`eb.log' records all the output from `EBMON', including echoes of the
+commands sent to it. Running `tail -f' on this file in another window
+often helps to understand trouble with `EBMON', or unexpected events on
+the PC side of the connection.
+
+
+File: gdb.info, Node: ST2000 Remote, Next: Hitachi Remote, Prev: VxWorks Remote, Up: Remote
+
+GDB with a Tandem ST2000
+------------------------
+
+ To connect your ST2000 to the host system, see the manufacturer's
+manual. Once the ST2000 is physically attached, you can run
+
+ target st2000 DEV SPEED
+
+to establish it as your debugging environment. DEV is normally the
+name of a serial device, such as `/dev/ttya', connected to the ST2000
+via a serial line. You can instead specify DEV as a TCP connection
+(for example, to a serial line attached via a terminal concentrator)
+using the syntax `HOSTNAME:PORTNUMBER'.
+
+ The `load' and `attach' commands are *not* defined for this target;
+you must load your program into the ST2000 as you normally would for
+standalone operation. GDB will read debugging information (such as
+symbols) from a separate, debugging version of the program available on
+your host computer.
+
+ These auxiliary GDB commands are available to help you with the
+ST2000 environment:
+
+`st2000 COMMAND'
+ Send a COMMAND to the STDBUG monitor. See the manufacturer's
+ manual for available commands.
+
+`connect'
+ Connect the controlling terminal to the STDBUG command monitor.
+ When you are done interacting with STDBUG, typing either of two
+ character sequences will get you back to the GDB command prompt:
+ `RET~.' (Return, followed by tilde and period) or `RET~C-d'
+ (Return, followed by tilde and control-D).
+
+
+File: gdb.info, Node: VxWorks Remote, Next: ST2000 Remote, Prev: EB29K Remote, Up: Remote
+
+GDB and VxWorks
+---------------
+
+ GDB 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. GDB uses code that runs on
+both the Unix host and on the VxWorks target. The program `gdb' is
+installed and executed on the Unix host. (It may be installed with the
+name `vxgdb', to distinguish it from a GDB for debugging programs on
+the host itself.)
+
+ The following information on connecting to VxWorks was current when
+this manual was produced; newer releases of VxWorks may use revised
+procedures.
+
+ The remote debugging interface (RDB) routines are installed and
+executed on the VxWorks target. These routines are included in the
+VxWorks library `rdb.a' and are incorporated into the system image when
+source-level debugging is enabled in the VxWorks configuration.
+
+ If you wish, you can define `INCLUDE_RDB' in the VxWorks
+configuration file `configAll.h' to include the RDB interface routines
+and spawn the source debugging task `tRdbTask' when VxWorks is booted.
+For more information on configuring and remaking VxWorks, see the
+manufacturer's manual.
+
+ Once you have included the RDB interface in your VxWorks system image
+and set your Unix execution search path to find GDB, you are ready to
+run GDB. From your Unix host, run `gdb' (or `vxgdb', depending on your
+installation).
+
+ GDB comes up showing the prompt:
+
+ (vxgdb)
+
+* Menu:
+
+* VxWorks Connection:: Connecting to VxWorks
+* VxWorks Download:: VxWorks download
+* VxWorks Attach:: Running tasks
+
+
+File: gdb.info, Node: VxWorks Connection, Next: VxWorks Download, Up: VxWorks Remote
+
+Connecting to VxWorks
+---------------------
+
+ The GDB command `target' lets you connect to a VxWorks target on the
+network. To connect to a target whose host name is "`tt'", type:
+
+ (vxgdb) target vxworks tt
+
+ GDB displays messages like these:
+
+ Attaching remote machine across net...
+ Connected to tt.
+
+ GDB then attempts to read the symbol tables of any object modules
+loaded into the VxWorks target since it was last booted. GDB locates
+these files by searching the directories listed in the command search
+path (*note Your program's environment: Environment.); if it fails to
+find an object file, it displays a message such as:
+
+ prog.o: No such file or directory.
+
+ When this happens, add the appropriate directory to the search path
+with the GDB command `path', and execute the `target' command again.
+
+
+File: gdb.info, Node: VxWorks Download, Next: VxWorks Attach, Prev: VxWorks Connection, Up: VxWorks Remote
+
+VxWorks download
+----------------
+
+ 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 GDB `load' command
+to download a file from Unix to VxWorks incrementally. The object file
+given as an argument to the `load' command is actually opened twice:
+first by the VxWorks target in order to download the code, then by GDB
+in order to read the symbol table. This can lead to problems if the
+current working directories on the two systems differ. If both systems
+have NFS mounted the same filesystems, you can avoid these problems by
+using absolute paths. Otherwise, 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.
+For instance, a program `prog.o' may reside in `VXPATH/vw/demo/rdb' in
+VxWorks and in `HOSTPATH/vw/demo/rdb' on the host. To load this
+program, type this on VxWorks:
+
+ -> cd "VXPATH/vw/demo/rdb"
+
+ Then, in GDB, type:
+
+ (vxgdb) cd HOSTPATH/vw/demo/rdb
+ (vxgdb) load prog.o
+
+ GDB displays a response similar to this:
+
+ Reading symbol data from wherever/vw/demo/rdb/prog.o... done.
+
+ You can also use the `load' command to reload an object module after
+editing and recompiling the corresponding source file. Note that this
+will cause GDB 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.)
+
+
+File: gdb.info, Node: VxWorks Attach, Prev: VxWorks Download, Up: VxWorks Remote
+
+Running tasks
+-------------
+
+ You can also attach to an existing task using the `attach' command as
+follows:
+
+ (vxgdb) attach TASK
+
+where TASK 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.
+
+
+File: gdb.info, Node: Hitachi Remote, Next: MIPS Remote, Prev: ST2000 Remote, Up: Remote
+
+GDB and Hitachi Microprocessors
+-------------------------------
+
+ GDB needs to know these things to talk to your Hitachi SH, H8/300,
+or H8/500:
+
+ 1. that you want to use `target hms', the remote debugging interface
+ for Hitachi microprocessors (this is the default when GDB is
+ configured specifically for the Hitachi SH, H8/300, or H8/500);
+
+ 2. what serial device connects your host to your Hitachi board (the
+ first serial device available on your host is the default);
+
+
+ Use the special `gdb' command `device PORT' if you need to
+explicitly set the serial device. The default PORT is the first
+available port on your host. This is only necessary on Unix hosts,
+where it is typically something like `/dev/ttya'.
+
+ `gdb' has another special command to set the communications speed:
+`speed BPS'. This command also is only used from Unix hosts; on DOS
+hosts, set the line speed as usual from outside GDB with the DOS `mode'
+command (for instance, `mode com2:9600,n,8,1,p' for a 9600 bps
+connection).
+
+ The `device' and `speed' commands are available only when you use a
+Unix host to debug your Hitachi microprocessor programs. If you use a
+DOS host, GDB depends on an auxiliary terminate-and-stay-resident
+program called `asynctsr' to communicate with the development board
+through a PC serial port. You must also use the DOS `mode' command to
+set up the serial port on the DOS side.
+
+
+File: gdb.info, Node: MIPS Remote, Next: Simulator, Prev: Hitachi Remote, Up: Remote
+
+GDB and remote MIPS boards
+--------------------------
+
+ GDB can use the MIPS remote debugging protocol to talk to a MIPS
+board attached to a serial line. This is available when you configure
+GDB with `--target=mips-idt-ecoff'.
+
+ To run a program on the board, start up `gdb' with the name of your
+program as the argument. To connect to the board, use the command
+`target mips PORT', where PORT is the name of the serial port connected
+to the board. If the program has not already been downloaded to the
+board, you may use the `load' command to download it. You can then use
+all the usual GDB commands.
+
+ You can also specify PORT as a TCP connection (for instance, to a
+serial line managed by a terminal concentrator), using the syntax
+`HOSTNAME:PORTNUMBER'.
+
+ You can see some debugging information about communications with the
+board by setting the `remotedebug' variable. If you set it to 1 using
+`set remotedebug 1' every packet will be displayed. If you set it to 2
+every character will be displayed. You can check the current value at
+any time with the command `show remotedebug'.
+
+ You can control the timeout used while waiting for a packet, in the
+MIPS remote protocol, with the `set timeout SECONDS' command. The
+default is 5 seconds. Similarly, you can control the timeout used while
+waiting for an acknowledgement of a packet with the `set
+retransmit-timeout SECONDS' command. The default is 3 seconds. You
+can inspect both values with `show timeout' and `show
+retransmit-timeout'. (These commands are *only* available when GDB is
+configured for `--target=mips-idt-ecoff'.)
+
+ If your target board does not support the MIPS floating point
+coprocessor, you should use the command `set mipsfpu off' (you may wish
+to put this in your .gdbinit file). This tells GDB how to find the
+return value of functions which return floating point values. It also
+allows GDB to avoid saving the floating point registers when calling
+functions on the board.
+
+
+File: gdb.info, Node: Simulator, Prev: MIPS Remote, Up: Remote
+
+Simulated CPU target
+--------------------
+
+ For some configurations, GDB includes a CPU simulator that you can
+use instead of a hardware CPU to debug your programs. Currently, a
+simulator is available when GDB is configured to debug Zilog Z8000 or
+Hitachi microprocessor targets.
+
+ For the Z8000 family, `target sim' simulates either the Z8002 (the
+unsegmented variant of the Z8000 architecture) or the Z8001 (the
+segmented variant). The simulator recognizes which architecture is
+appropriate by inspecting the object code.
+
+`target sim'
+ Debug programs on a simulated CPU (which CPU depends on the GDB
+ configuration)
+
+After specifying this target, you can debug programs for the simulated
+CPU in the same style as programs for your host computer; use the
+`file' command to load a new program image, the `run' command to run
+your program, and so on.
+
+ As well as making available all the usual machine registers (see
+`info reg'), this debugging target provides three additional items of
+information as specially named registers:
+
+`cycles'
+ Counts clock-ticks in the simulator.
+
+`insts'
+ Counts instructions run in the simulator.
+
+`time'
+ Execution time in 60ths of a second.
+
+ You can refer to these values in GDB expressions with the usual
+conventions; for example, `b fputc if $cycles>5000' sets a conditional
+breakpoint that will suspend only after at least 5000 simulated clock
+ticks.
+
+
+File: gdb.info, Node: Controlling GDB, Next: Sequences, Prev: Targets, Up: Top
+
+Controlling GDB
+***************
+
+ You can alter the way GDB interacts with you by using the `set'
+command. For commands controlling how GDB displays data, *note Print
+settings: Print Settings.; other settings are described here.
+
+* Menu:
+
+* Prompt:: Prompt
+* Editing:: Command editing
+* History:: Command history
+* Screen Size:: Screen size
+* Numbers:: Numbers
+* Messages/Warnings:: Optional warnings and messages
+
+
+File: gdb.info, Node: Prompt, Next: Editing, Up: Controlling GDB
+
+Prompt
+======
+
+ GDB indicates its readiness to read a command by printing a string
+called the "prompt". This string is normally `(gdb)'. You can change
+the prompt string with the `set prompt' command. For instance, when
+debugging GDB with GDB, it is useful to change the prompt in one of the
+GDB sessions so that you can always tell which one you are talking to.
+
+`set prompt NEWPROMPT'
+ Directs GDB to use NEWPROMPT as its prompt string henceforth.
+
+`show prompt'
+ Prints a line of the form: `Gdb's prompt is: YOUR-PROMPT'
+
+
+File: gdb.info, Node: Editing, Next: History, Prev: Prompt, Up: Controlling GDB
+
+Command editing
+===============
+
+ GDB reads its input commands via the "readline" interface. This GNU
+library provides consistent behavior for programs which provide a
+command line interface to the user. Advantages are `emacs'-style or
+`vi'-style inline editing of commands, `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 GDB with the
+command `set'.
+
+`set editing'
+`set editing on'
+ Enable command line editing (enabled by default).
+
+`set editing off'
+ Disable command line editing.
+
+`show editing'
+ Show whether command line editing is enabled.
+
+
+File: gdb.info, Node: History, Next: Screen Size, Prev: Editing, Up: Controlling GDB
+
+Command history
+===============
+
+ GDB can keep track of the commands you type during your debugging
+sessions, so that you can be certain of precisely what happened. Use
+these commands to manage the GDB command history facility.
+
+`set history filename FNAME'
+ Set the name of the GDB command history file to FNAME. This is
+ the file from which GDB 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 environment variable `GDBHISTFILE', or to `./.gdb_history'
+ if this variable is not set.
+
+`set history save'
+`set history save on'
+ Record command history in a file, whose name may be specified with
+ the `set history filename' command. By default, this option is
+ disabled.
+
+`set history save off'
+ Stop recording command history in a file.
+
+`set history size SIZE'
+ Set the number of commands which GDB will keep in its history list.
+ This defaults to the value of the environment variable `HISTSIZE',
+ or to 256 if this variable is not set.
+
+ History expansion assigns special meaning to the character `!'.
+
+ Since `!' is also the logical not operator in C, history expansion
+is off by default. If you decide to enable history expansion with the
+`set history expansion on' command, you may sometimes need to follow
+`!' (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 `!=' and `!(',
+even when history expansion is enabled.
+
+ The commands to control history expansion are:
+
+`set history expansion on'
+`set history expansion'
+ Enable history expansion. History expansion is off by default.
+
+`set history expansion off'
+ Disable history expansion.
+
+ The readline code comes with more complete documentation of
+ editing and history expansion features. Users unfamiliar with
+ `emacs' or `vi' may wish to read it.
+
+`show history'
+`show history filename'
+`show history save'
+`show history size'
+`show history expansion'
+ These commands display the state of the GDB history parameters.
+ `show history' by itself displays all four states.
+
+`show commands'
+ Display the last ten commands in the command history.
+
+`show commands N'
+ Print ten commands centered on command number N.
+
+`show commands +'
+ Print ten commands just after the commands last printed.
+
+
+File: gdb.info, Node: Screen Size, Next: Numbers, Prev: History, Up: Controlling GDB
+
+Screen size
+===========
+
+ Certain commands to GDB may produce large amounts of information
+output to the screen. To help you read all of it, GDB pauses and asks
+you for input at the end of each page of output. Type RET when you
+want to continue the output, or `q' to discard the remaining output.
+Also, the screen width setting determines when to wrap lines of output.
+Depending on what is being printed, GDB tries to break the line at a
+readable place, rather than simply letting it overflow onto the
+following line.
+
+ Normally GDB knows the size of the screen from the termcap data base
+together with the value of the `TERM' environment variable and the
+`stty rows' and `stty cols' settings. If this is not correct, you can
+override it with the `set height' and `set width' commands:
+
+`set height LPP'
+`show height'
+`set width CPL'
+`show width'
+ These `set' commands specify a screen height of LPP lines and a
+ screen width of CPL characters. The associated `show' commands
+ display the current settings.
+
+ If you specify a height of zero lines, GDB 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.
+
+ Likewise, you can specify `set width 0' to prevent GDB from
+ wrapping its output.
+
+
+File: gdb.info, Node: Numbers, Next: Messages/Warnings, Prev: Screen Size, Up: Controlling GDB
+
+Numbers
+=======
+
+ You can always enter numbers in octal, decimal, or hexadecimal in
+GDB by the usual conventions: octal numbers begin with `0', decimal
+numbers end with `.', and hexadecimal numbers begin with `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 `set radix' command.
+
+`set radix BASE'
+ Set the default base for numeric input and display. Supported
+ choices for BASE are decimal 8, 10, or 16. BASE must itself be
+ specified either unambiguously or using the current default radix;
+ for example, any of
+
+ set radix 012
+ set radix 10.
+ set radix 0xa
+
+ will set the base to decimal. On the other hand, `set radix 10'
+ will leave the radix unchanged no matter what it was.
+
+`show radix'
+ Display the current default base for numeric input and display.
+
+
+File: gdb.info, Node: Messages/Warnings, Prev: Numbers, Up: Controlling GDB
+
+Optional warnings and messages
+==============================
+
+ By default, GDB is silent about its inner workings. If you are
+running on a slow machine, you may want to use the `set verbose'
+command. It will make GDB tell you when it does a lengthy internal
+operation, so you will not think it has crashed.
+
+ Currently, the messages controlled by `set verbose' are those which
+announce that the symbol table for a source file is being read; see
+`symbol-file' in *Note Commands to specify files: Files.
+
+`set verbose on'
+ Enables GDB output of certain informational messages.
+
+`set verbose off'
+ Disables GDB output of certain informational messages.
+
+`show verbose'
+ Displays whether `set verbose' is on or off.
+
+ By default, if GDB encounters bugs in the symbol table of an object
+file, it is silent; but if you are debugging a compiler, you may find
+this information useful (*note Errors reading symbol files: Symbol
+Errors.).
+
+`set complaints LIMIT'
+ Permits GDB to output LIMIT complaints about each type of unusual
+ symbols before becoming silent about the problem. Set LIMIT to
+ zero to suppress all complaints; set it to a large number to
+ prevent complaints from being suppressed.
+
+`show complaints'
+ Displays how many symbol complaints GDB is permitted to produce.
+
+ By default, GDB is cautious, and asks what sometimes seems to be a
+lot of stupid questions to confirm certain commands. For example, if
+you try to run a program which is already running:
+
+ (gdb) run
+ The program being debugged has been started already.
+ Start it from the beginning? (y or n)
+
+ If you are willing to unflinchingly face the consequences of your own
+commands, you can disable this "feature":
+
+`set confirm off'
+ Disables confirmation requests.
+
+`set confirm on'
+ Enables confirmation requests (the default).
+
+`show confirm'
+ Displays state of confirmation requests.
+
+ Some systems allow individual object files that make up your program
+to be replaced without stopping and restarting your program. For
+example, in VxWorks you can simply recompile a defective object file
+and keep on running. If you are running on one of these systems, you
+can allow GDB to reload the symbols for automatically relinked modules:
+
+`set symbol-reloading on'
+ Replace symbol definitions for the corresponding source file when
+ an object file with a particular name is seen again.
+
+`set symbol-reloading off'
+ Do not replace symbol definitions when re-encountering object
+ files of the same name. This is the default state; if you are not
+ running on a system that permits automatically relinking modules,
+ you should leave `symbol-reloading' off, since otherwise GDB may
+ discard symbols when linking large programs, that may contain
+ several modules (from different directories or libraries) with the
+ same name.
+
+`show symbol-reloading'
+ Show the current `on' or `off' setting.
+
+
+File: gdb.info, Node: Sequences, Next: Emacs, Prev: Controlling GDB, Up: Top
+
+Canned Sequences of Commands
+****************************
+
+ Aside from breakpoint commands (*note Breakpoint command lists:
+Break Commands.), GDB provides two ways to store sequences of commands
+for execution as a unit: user-defined commands and command files.
+
+* Menu:
+
+* Define:: User-defined commands
+* Hooks:: User-defined command hooks
+* Command Files:: Command files
+* Output:: Commands for controlled output
+
+
+File: gdb.info, Node: Define, Next: Hooks, Up: Sequences
+
+User-defined commands
+=====================
+
+ A "user-defined command" is a sequence of GDB commands to which you
+assign a new name as a command. This is done with the `define' command.
+
+`define COMMANDNAME'
+ Define a command named 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 GDB command
+ lines, which are given following the `define' command. The end of
+ these commands is marked by a line containing `end'.
+
+`document COMMANDNAME'
+ Give documentation to the user-defined command COMMANDNAME. The
+ command COMMANDNAME must already be defined. This command reads
+ lines of documentation just as `define' reads the lines of the
+ command definition, ending with `end'. After the `document'
+ command is finished, `help' on command COMMANDNAME will print the
+ documentation you have specified.
+
+ You may use the `document' command again to change the
+ documentation of a command. Redefining the command with `define'
+ does not change the documentation.
+
+`help user-defined'
+ List all user-defined commands, with the first line of the
+ documentation (if any) for each.
+
+`show user'
+`show user COMMANDNAME'
+ Display the GDB commands used to define COMMANDNAME (but not its
+ documentation). If no COMMANDNAME is given, display the
+ definitions for all user-defined commands.
+
+ 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
+GDB commands that normally print messages to say what they are doing
+omit the messages when used in a user-defined command.
+
+
+File: gdb.info, Node: Hooks, Next: Command Files, Prev: Define, Up: Sequences
+
+User-defined command hooks
+==========================
+
+ You may define *hooks*, which are a special kind of user-defined
+command. Whenever you run the command `foo', if the user-defined
+command `hook-foo' exists, it is executed (with no arguments) before
+that command.
+
+ In addition, a pseudo-command, `stop' exists. Defining
+(`hook-stop') makes the associated commands execute every time
+execution stops in your program: before breakpoint commands are run,
+displays are printed, or the stack frame is printed.
+
+ For example, to ignore `SIGALRM' signals while single-stepping, but
+treat them normally during normal execution, you could define:
+
+ define hook-stop
+ handle SIGALRM nopass
+ end
+
+ define hook-run
+ handle SIGALRM pass
+ end
+
+ define hook-continue
+ handle SIGLARM pass
+ end
+
+ You can define a hook for any single-word command in GDB, but not
+for command aliases; you should define a hook for the basic command
+name, e.g. `backtrace' rather than `bt'. If an error occurs during
+the execution of your hook, execution of GDB commands stops and GDB
+issues a prompt (before the command that you actually typed had a
+chance to run).
+
+ If you try to define a hook which does not match any known command,
+you will get a warning from the `define' command.
+
+
+File: gdb.info, Node: Command Files, Next: Output, Prev: Hooks, Up: Sequences
+
+Command files
+=============
+
+ A command file for GDB is a file of lines that are GDB commands.
+Comments (lines starting with `#') 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.
+
+ When you start GDB, it automatically executes commands from its
+"init files". These are files named `.gdbinit'. GDB 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 you
+use the `-nx' option; *note Choosing modes: Mode Options..)
+
+ On some configurations of GDB, the init file is known by a different
+name (these are typically environments where a specialized form of GDB
+may need to coexist with other forms, hence a different name for the
+specialized version's init file). These are the environments with
+special init file names:
+
+ * VxWorks (Wind River Systems real-time OS): `.vxgdbinit'
+
+ * OS68K (Enea Data Systems real-time OS): `.os68gdbinit'
+
+ * ES-1800 (Ericsson Telecom AB M68000 emulator): `.esgdbinit'
+
+ You can also request the execution of a command file with the
+`source' command:
+
+`source FILENAME'
+ Execute the command file FILENAME.
+
+ 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 GDB commands
+that normally print messages to say what they are doing omit the
+messages when called from command files.
+
+
+File: gdb.info, Node: Output, Prev: Command Files, Up: Sequences
+
+Commands for controlled output
+==============================
+
+ During the execution of a command file or a user-defined command,
+normal GDB output is suppressed; the only output that appears is what is
+explicitly printed by the commands in the definition. This section
+describes three commands useful for generating exactly the output you
+want.
+
+`echo TEXT'
+ Print TEXT. Nonprinting characters can be included in TEXT using
+ C escape sequences, such as `\n' to print a newline. *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 displaying a string with
+ spaces at the beginning or the end, since leading and trailing
+ spaces are otherwise trimmed from all arguments. To print ` and
+ foo = ', use the command `echo \ and foo = \ '.
+
+ A backslash at the end of TEXT can be used, as in C, to continue
+ the command onto subsequent lines. For example,
+
+ echo This is some text\n\
+ which is continued\n\
+ onto several lines.\n
+
+ produces the same output as
+
+ echo This is some text\n
+ echo which is continued\n
+ echo onto several lines.\n
+
+`output EXPRESSION'
+ Print the value of EXPRESSION and nothing but that value: no
+ newlines, no `$NN = '. The value is not entered in the value
+ history either. *Note Expressions: Expressions, for more
+ information on expressions.
+
+`output/FMT EXPRESSION'
+ Print the value of EXPRESSION in format FMT. You can use the same
+ formats as for `print'. *Note Output formats: Output Formats, for
+ more information.
+
+`printf STRING, EXPRESSIONS...'
+ Print the values of the EXPRESSIONS under the control of STRING.
+ The EXPRESSIONS are separated by commas and may be either numbers
+ or pointers. Their values are printed as specified by STRING,
+ exactly as if your program were to execute the C subroutine
+
+ printf (STRING, EXPRESSIONS...);
+
+ For example, you can print two values in hex like this:
+
+ printf "foo, bar-foo = 0x%x, 0x%x\n", foo, bar-foo
+
+ 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.
+
+
+File: gdb.info, Node: Emacs, Next: GDB Bugs, Prev: Sequences, Up: Top
+
+Using GDB under GNU Emacs
+*************************
+
+ A special interface allows you to use GNU Emacs to view (and edit)
+the source files for the program you are debugging with GDB.
+
+ To use this interface, use the command `M-x gdb' in Emacs. Give the
+executable file you want to debug as an argument. This command starts
+GDB as a subprocess of Emacs, with input and output through a newly
+created Emacs buffer.
+
+ Using GDB under Emacs is just like using GDB normally except for two
+things:
+
+ * All "terminal" input and output goes through the Emacs buffer.
+
+ This applies both to GDB 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 interacting
+with your program. In particular, you can send signals the usual
+way--for example, `C-c C-c' for an interrupt, `C-c C-z' for a stop.
+
+ * GDB displays source code through Emacs.
+
+ Each time GDB displays a stack frame, Emacs automatically finds the
+source file for that frame and puts an arrow (`=>') at the left margin
+of the current line. Emacs uses a separate buffer for source display,
+and splits the screen to show both your GDB session and the source.
+
+ Explicit GDB `list' or search commands still produce output as
+usual, but you probably will have no reason to use them.
+
+ *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. GDB can find programs
+ by searching your environment's `PATH' variable, so the GDB input
+ and output session will proceed normally; but Emacs does not get
+ enough information back from GDB to locate the source files in
+ this situation. To avoid this problem, either start GDB mode from
+ the directory where your program resides, or specify a full path
+ name when prompted for the `M-x gdb' argument.
+
+ A similar confusion can result if you use the GDB `file' command to
+ switch to debugging a program in some other location, from an
+ existing GDB buffer in Emacs.
+
+ By default, `M-x gdb' calls the program called `gdb'. If you need
+to call GDB by a different name (for example, if you keep several
+configurations around, with different names) you can set the Emacs
+variable `gdb-command-name'; for example,
+
+ (setq gdb-command-name "mygdb")
+
+(preceded by `ESC ESC', or typed in the `*scratch*' buffer, or in your
+`.emacs' file) will make Emacs call the program named "`mygdb'" instead.
+
+ In the GDB I/O buffer, you can use these special Emacs commands in
+addition to the standard Shell mode commands:
+
+`C-h m'
+ Describe the features of Emacs' GDB Mode.
+
+`M-s'
+ Execute to another source line, like the GDB `step' command; also
+ update the display window to show the current file and location.
+
+`M-n'
+ Execute to next source line in this function, skipping all function
+ calls, like the GDB `next' command. Then update the display window
+ to show the current file and location.
+
+`M-i'
+ Execute one instruction, like the GDB `stepi' command; update
+ display window accordingly.
+
+`M-x gdb-nexti'
+ Execute to next instruction, using the GDB `nexti' command; update
+ display window accordingly.
+
+`C-c C-f'
+ Execute until exit from the selected stack frame, like the GDB
+ `finish' command.
+
+`M-c'
+ Continue execution of your program, like the GDB `continue'
+ command.
+
+ *Warning:* In Emacs v19, this command is `C-c C-p'.
+
+`M-u'
+ Go up the number of frames indicated by the numeric argument
+ (*note Numeric Arguments: (emacs)Arguments.), like the GDB `up'
+ command.
+
+ *Warning:* In Emacs v19, this command is `C-c C-u'.
+
+`M-d'
+ Go down the number of frames indicated by the numeric argument,
+ like the GDB `down' command.
+
+ *Warning:* In Emacs v19, this command is `C-c C-d'.
+
+`C-x &'
+ Read the number where the cursor is positioned, and insert it at
+ the end of the GDB I/O buffer. For example, if you wish to
+ disassemble code around an address that was displayed earlier,
+ type `disassemble'; then move the cursor to the address display,
+ and pick up the argument for `disassemble' by typing `C-x &'.
+
+ You can customize this further by defining elements of the list
+ `gdb-print-command'; once it is defined, you can format or
+ otherwise process numbers picked up by `C-x &' before they are
+ inserted. A numeric argument to `C-x &' will both indicate 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 `format';
+ otherwise the number is passed as an argument to the corresponding
+ list element.
+
+ In any source file, the Emacs command `C-x SPC' (`gdb-break') tells
+GDB to set a breakpoint on the source line point is on.
+
+ If you accidentally delete the source-display buffer, an easy way to
+get it back is to type the command `f' in the GDB buffer, to request a
+frame display; when you run under Emacs, this will recreate the source
+buffer if necessary to show you the context of the current frame.
+
+ 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 GDB
+communicates with Emacs in terms of line numbers. If you add or delete
+lines from the text, the line numbers that GDB knows will cease to
+correspond properly with the code.
+
+
+File: gdb.info, Node: GDB Bugs, Next: Command Line Editing, Prev: Emacs, Up: Top
+
+Reporting Bugs in GDB
+*********************
+
+ Your bug reports play an essential role in making GDB 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 GDB work
+better. Bug reports are your contribution to the maintenance of GDB.
+
+ In order for a bug report to serve its purpose, you must include the
+information that enables us to fix the bug.
+
+* Menu:
+
+* Bug Criteria:: Have you found a bug?
+* Bug Reporting:: How to report bugs
+
+
+File: gdb.info, Node: Bug Criteria, Next: Bug Reporting, Up: GDB Bugs
+
+Have you found a bug?
+=====================
+
+ If you are not sure whether you have found a bug, here are some
+guidelines:
+
+ * If the debugger gets a fatal signal, for any input whatever, that
+ is a GDB bug. Reliable debuggers never crash.
+
+ * If GDB produces an error message for valid input, that is a bug.
+
+ * If GDB 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".
+
+ * If you are an experienced user of debugging tools, your suggestions
+ for improvement of GDB are welcome in any case.
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.info-7 b/gnu/usr.bin/gdb/doc/gdb.info-7
new file mode 100644
index 000000000000..963527ef774a
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info-7
@@ -0,0 +1,1233 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+File: gdb.info, Node: Bug Reporting, Prev: Bug Criteria, Up: GDB Bugs
+
+How to report bugs
+==================
+
+ A number of companies and individuals offer support for GNU products.
+If you obtained GDB from a support organization, we recommend you
+contact that organization first.
+
+ You can find contact information for many support companies and
+individuals in the file `etc/SERVICE' in the GNU Emacs distribution.
+
+ In any event, we also recommend that you send bug reports for GDB to
+one of these addresses:
+
+ bug-gdb@prep.ai.mit.edu
+ {ucbvax|mit-eddie|uunet}!prep.ai.mit.edu!bug-gdb
+
+ *Do not send bug reports to `info-gdb', or to `help-gdb', or to any
+newsgroups.* Most users of GDB do not want to receive bug reports.
+Those that do, have arranged to receive `bug-gdb'.
+
+ The mailing list `bug-gdb' has a newsgroup `gnu.gdb.bug' 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 often lacks 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:
+
+ GNU Debugger Bugs
+ Free Software Foundation
+ 545 Tech Square
+ Cambridge, MA 02139
+
+ The fundamental principle of reporting bugs usefully is this:
+*report all the facts*. If you are not sure whether to state a fact or
+leave it out, state it!
+
+ Often people omit facts because they think they know what causes the
+problem and assume that some details do not matter. Thus, you might
+assume that the name of the variable you use in an example does not
+matter. Well, probably it does not, but one cannot be sure. Perhaps
+the bug is a stray memory reference which happens to fetch from the
+location where that 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 is not as important as 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 *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:
+
+ * The version of GDB. GDB announces it if you start with no
+ arguments; you can also print it at any time using `show version'.
+
+ Without this, we will not know whether there is any point in
+ looking for the bug in the current version of GDB.
+
+ * The type of machine you are using, and the operating system name
+ and version number.
+
+ * What compiler (and its version) was used to compile GDB--e.g.
+ "gcc-2.0".
+
+ * What compiler (and its version) was used to compile the program you
+ are debugging--e.g. "gcc-2.0".
+
+ * The command arguments you gave the compiler to compile your
+ example and observe the bug. For example, did you use `-O'? To
+ guarantee you will not omit something important, list them all. A
+ copy of the Makefile (or the output from make) is sufficient.
+
+ If we were to try to guess the arguments, we would probably guess
+ wrong and then we might not encounter the bug.
+
+ * A complete input script, and all necessary source files, that will
+ reproduce the bug.
+
+ * 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 GDB 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. We are human, after all.
+ You might as well not give us a chance to make a mistake.
+
+ Even if the problem you experience is a fatal signal, you should
+ still say so explicitly. Suppose something strange is going on,
+ such as, your copy of GDB is out of synch, or you have encountered
+ a bug in the C library on your system. (This has happened!) Your
+ copy might crash and ours would not. If you told us to expect a
+ crash, then when ours fails to crash, we would know that the bug
+ was not happening for us. If you had not told us to expect a
+ crash, then we would not be able to draw any conclusion from our
+ observations.
+
+ * If you wish to suggest changes to the GDB source, send us context
+ diffs. If you even discuss something in the GDB source, refer to
+ it by context, not by line number.
+
+ The line numbers in our development sources will not match those
+ in your sources. Your line numbers would convey no useful
+ information to us.
+
+ Here are some things that are not necessary:
+
+ * 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 *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 do not want to do
+ this, report the bug anyway and send us the entire test case you
+ used.
+
+ * A patch for the bug.
+
+ A patch for the bug does help us if it is a good one. But do not
+ omit the necessary information, such as the test case, on the
+ assumption that a patch is all we need. We might see problems
+ with your patch and decide to fix the problem another way, or we
+ might not understand it at all.
+
+ Sometimes with a program as complicated as GDB it is very hard to
+ construct an example that will make the program follow a certain
+ path through the code. If you do not send us the example, we will
+ not be able to construct one, so we will not be able to verify
+ that the bug is fixed.
+
+ And if we cannot understand what bug you are trying to fix, or why
+ your patch should be an improvement, we will not install it. A
+ test case will help us to understand.
+
+ * A guess about what the bug is or what it depends on.
+
+ Such guesses are usually wrong. Even we cannot guess right about
+ such things without first using the debugger to find the facts.
+
+
+File: gdb.info, Node: Command Line Editing, Next: Using History Interactively, Prev: GDB Bugs, Up: Top
+
+Command Line Editing
+********************
+
+ This text describes GNU's command line editing interface.
+
+* Menu:
+
+* Introduction and Notation:: Notation used in this text.
+* Readline Interaction:: The minimum set of commands for editing a line.
+* Readline Init File:: Customizing Readline from a user's view.
+
+
+File: gdb.info, Node: Introduction and Notation, Next: Readline Interaction, Up: Command Line Editing
+
+Introduction to Line Editing
+============================
+
+ The following paragraphs describe the notation we use to represent
+keystrokes.
+
+ The text C-k is read as `Control-K' and describes the character
+produced when the Control key is depressed and the k key is struck.
+
+ The text M-k is read as `Meta-K' and describes the character
+produced when the meta key (if you have one) is depressed, and the k
+key is struck. If you do not have a meta key, the identical keystroke
+can be generated by typing ESC first, and then typing k. Either
+process is known as "metafying" the k key.
+
+ The text M-C-k is read as `Meta-Control-k' and describes the
+character produced by "metafying" C-k.
+
+ In addition, several keys have their own names. Specifically, DEL,
+ESC, LFD, SPC, RET, and TAB all stand for themselves when seen in this
+text, or in an init file (*note Readline Init File::., for more info).
+
+
+File: gdb.info, Node: Readline Interaction, Next: Readline Init File, Prev: Introduction and Notation, Up: Command Line Editing
+
+Readline Interaction
+====================
+
+ Often during an interactive session you 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 RETURN. You do not have to be at the end of
+the line to press RETURN; the entire line is accepted regardless of the
+location of the cursor within the line.
+
+* 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.
+
+
+File: gdb.info, Node: Readline Bare Essentials, Next: Readline Movement Commands, Up: Readline Interaction
+
+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 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 C-b to move the cursor to the
+left, and then correct your mistake. Aftwerwards, you can move the
+cursor to the right with 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.
+
+C-b
+ Move back one character.
+
+C-f
+ Move forward one character.
+
+DEL
+ Delete the character to the left of the cursor.
+
+C-d
+ Delete the character underneath the cursor.
+
+Printing characters
+ Insert itself into the line at the cursor.
+
+C-_
+ Undo the last thing that you did. You can undo all the way back
+ to an empty line.
+
+
+File: gdb.info, Node: Readline Movement Commands, Next: Readline Killing Commands, Prev: Readline Bare Essentials, Up: Readline Interaction
+
+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 C-b,
+C-f, C-d, and DEL. Here are some commands for moving more rapidly
+about the line.
+
+C-a
+ Move to the start of the line.
+
+C-e
+ Move to the end of the line.
+
+M-f
+ Move forward a word.
+
+M-b
+ Move backward a word.
+
+C-l
+ Clear the screen, reprinting the current line at the top.
+
+ Notice how C-f moves forward a character, while M-f moves forward a
+word. It is a loose convention that control keystrokes operate on
+characters while meta keystrokes operate on words.
+
+
+File: gdb.info, Node: Readline Killing Commands, Next: Readline Arguments, Prev: Readline Movement Commands, Up: Readline Interaction
+
+Readline Killing Commands
+-------------------------
+
+ "Killing" text means to delete the text from the line, but to save
+it away for later use, usually by "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.
+
+C-k
+ Kill the text from the current cursor position to the end of the
+ line.
+
+M-d
+ Kill from the cursor to the end of the current word, or if between
+ words, to the end of the next word.
+
+M-DEL
+ Kill from the cursor to the start of the previous word, or if
+ between words, to the start of the previous word.
+
+C-w
+ Kill from the cursor to the previous whitespace. This is
+ different than M-DEL because the word boundaries differ.
+
+ And, here is how to "yank" the text back into the line. Yanking is
+
+C-y
+ Yank the most recently killed text back into the buffer at the
+ cursor.
+
+M-y
+ Rotate the kill-ring, and yank the new top. You can only do this
+ if the prior command is C-y or M-y.
+
+ When you use a kill command, the text is saved in a "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.
+
+
+File: gdb.info, Node: Readline Arguments, Prev: Readline Killing Commands, Up: Readline Interaction
+
+Readline Arguments
+------------------
+
+ You can pass numeric arguments to Readline commands. Sometimes the
+argument acts as a repeat count, other times it is the 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 M- 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 (-), 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 C-d command an argument of 10, you could type M-1 0 C-d.
+
+
+File: gdb.info, Node: Readline Init File, Prev: Readline Interaction, Up: Command Line Editing
+
+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 "init" file in your home directory. The name of this
+file is `~/.inputrc'.
+
+ When a program which uses the Readline library starts up, the
+`~/.inputrc' file is read, and the keybindings are set.
+
+ In addition, the C-x C-r command re-reads this init file, thus
+incorporating any changes that you might have made to it.
+
+* Menu:
+
+* Readline Init Syntax:: Syntax for the commands in `~/.inputrc'.
+* Readline Vi Mode:: Switching to `vi' mode in Readline.
+
+
+File: gdb.info, Node: Readline Init Syntax, Next: Readline Vi Mode, Up: Readline Init File
+
+Readline Init Syntax
+--------------------
+
+ There are only four constructs allowed in the `~/.inputrc' file:
+
+Variable Settings
+ You can change the state of a few variables in Readline. You do
+ this by using the `set' command within the init file. Here is how
+ you would specify that you wish to use Vi line editing commands:
+
+ set editing-mode vi
+
+ Right now, there are only a few variables which can be set; so few
+ in fact, that we just iterate them here:
+
+ `editing-mode'
+ The `editing-mode' variable controls which editing mode you
+ are using. By default, GNU Readline starts up in Emacs
+ editing mode, where the keystrokes are most similar to Emacs.
+ This variable can either be set to `emacs' or `vi'.
+
+ `horizontal-scroll-mode'
+ This variable can either be set to `On' or `Off'. Setting it
+ to `On' means that the text of the lines that you edit will
+ scroll horizontally on a single screen line when they are
+ larger than the width of the screen, instead of wrapping onto
+ a new screen line. By default, this variable is set to `Off'.
+
+ `mark-modified-lines'
+ This variable when set to `On', says to display an asterisk
+ (`*') at the starts of history lines which have been modified.
+ This variable is off by default.
+
+ `prefer-visible-bell'
+ If this variable is set to `On' it means to use a visible
+ bell if one is available, rather than simply ringing the
+ terminal bell. By default, the value is `Off'.
+
+Key Bindings
+ The syntax for controlling keybindings in the `~/.inputrc' file is
+ simple. First you have to know the 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 `~/.inputrc' file. The name
+ of the key can be expressed in different ways, depending on which
+ is most comfortable for you.
+
+ KEYNAME: FUNCTION-NAME or MACRO
+ KEYNAME is the name of a key spelled out in English. For
+ example:
+ Control-u: universal-argument
+ Meta-Rubout: backward-kill-word
+ Control-o: ">&output"
+
+ In the above example, C-u is bound to the function
+ `universal-argument', and C-o is bound to run the macro
+ expressed on the right hand side (that is, to insert the text
+ `>&output' into the line).
+
+ "KEYSEQ": FUNCTION-NAME or MACRO
+ KEYSEQ differs from KEYNAME above in that strings denoting an
+ entire key sequence can be specified. Simply place the key
+ sequence in double quotes. GNU Emacs style key escapes can
+ be used, as in the following example:
+
+ "\C-u": universal-argument
+ "\C-x\C-r": re-read-init-file
+ "\e[11~": "Function Key 1"
+
+ In the above example, C-u is bound to the function
+ `universal-argument' (just as it was in the first example),
+ C-x C-r is bound to the function `re-read-init-file', and ESC
+ [ 1 1 ~ is bound to insert the text `Function Key 1'.
+
+* 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.
+
+
+File: gdb.info, Node: Commands For Moving, Next: Commands For History, Up: Readline Init Syntax
+
+Commands For Moving
+-------------------
+
+`beginning-of-line (C-a)'
+ Move to the start of the current line.
+
+`end-of-line (C-e)'
+ Move to the end of the line.
+
+`forward-char (C-f)'
+ Move forward a character.
+
+`backward-char (C-b)'
+ Move back a character.
+
+`forward-word (M-f)'
+ Move forward to the end of the next word.
+
+`backward-word (M-b)'
+ Move back to the start of this, or the previous, word.
+
+`clear-screen (C-l)'
+ Clear the screen leaving the current line at the top of the screen.
+
+
+File: gdb.info, Node: Commands For History, Next: Commands For Text, Prev: Commands For Moving, Up: Readline Init Syntax
+
+Commands For Manipulating The History
+-------------------------------------
+
+`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.
+
+`previous-history (C-p)'
+ Move `up' through the history list.
+
+`next-history (C-n)'
+ Move `down' through the history list.
+
+`beginning-of-history (M-<)'
+ Move to the first line in the history.
+
+`end-of-history (M->)'
+ Move to the end of the input history, i.e., the line you are
+ entering!
+
+`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.
+
+`forward-search-history (C-s)'
+ Search forward starting at the current line and moving `down'
+ through the the history as neccessary.
+
+
+File: gdb.info, Node: Commands For Text, Next: Commands For Killing, Prev: Commands For History, Up: Readline Init Syntax
+
+Commands For Changing Text
+--------------------------
+
+`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.
+
+`backward-delete-char (Rubout)'
+ Delete the character behind the cursor. A numeric arg says to kill
+ the characters instead of deleting them.
+
+`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.
+
+`tab-insert (M-TAB)'
+ Insert a tab character.
+
+`self-insert (a, b, A, 1, !, ...)'
+ Insert yourself.
+
+`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.
+
+`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.
+
+`upcase-word (M-u)'
+ Uppercase all letters in the current (or following) word. With a
+ negative argument, do the previous word, but do not move point.
+
+`downcase-word (M-l)'
+ Lowercase all letters in the current (or following) word. With a
+ negative argument, do the previous word, but do not move point.
+
+`capitalize-word (M-c)'
+ Uppercase the first letter in the current (or following) word.
+ With a negative argument, do the previous word, but do not move
+ point.
+
+
+File: gdb.info, Node: Commands For Killing, Next: Numeric Arguments, Prev: Commands For Text, Up: Readline Init Syntax
+
+Killing And Yanking
+-------------------
+
+`kill-line (C-k)'
+ Kill the text from the current cursor position to the end of the
+ line.
+
+`backward-kill-line ()'
+ Kill backward to the beginning of the line. This is normally
+ unbound.
+
+`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.
+
+`backward-kill-word (M-DEL)'
+ Kill the word behind the cursor.
+
+`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.
+
+`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.
+
+`yank (C-y)'
+ Yank the top of the kill ring into the buffer at point.
+
+`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.
+
+
+File: gdb.info, Node: Numeric Arguments, Next: Commands For Completion, Prev: Commands For Killing, Up: Readline Init Syntax
+
+Specifying Numeric Arguments
+----------------------------
+
+`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.
+
+`universal-argument ()'
+ Do what C-u does in emacs. By default, this is not bound.
+
+
+File: gdb.info, Node: Commands For Completion, Next: Miscellaneous Commands, Prev: Numeric Arguments, Up: Readline Init Syntax
+
+Letting Readline Type For You
+-----------------------------
+
+`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...
+
+`possible-completions (M-?)'
+ List the possible completions of the text before point.
+
+
+File: gdb.info, Node: Miscellaneous Commands, Prev: Commands For Completion, Up: Readline Init Syntax
+
+Some Miscellaneous Commands
+---------------------------
+
+`re-read-init-file (C-x C-r)'
+ Read in the contents of your `~/.inputrc' file, and incorporate
+ any bindings found there.
+
+`abort (C-g)'
+ Stop running the current editing command.
+
+`prefix-meta (ESC)'
+ Make the next character that you type be metafied. This is for
+ people without a meta key. Typing ESC f is equivalent to typing
+ M-f.
+
+`undo (C-_)'
+ Incremental undo, separately remembered for each line.
+
+`revert-line (M-r)'
+ Undo all changes made to this line. This is like typing the `undo'
+ command enough times to get back to the beginning.
+
+
+File: gdb.info, Node: Readline Vi Mode, Prev: Readline Init Syntax, Up: Readline Init File
+
+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 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.
+
+
+File: gdb.info, Node: Using History Interactively, Next: Renamed Commands, Prev: Command Line Editing, Up: Top
+
+Using History Interactively
+***************************
+
+ This chapter describes how to use the GNU History Library
+interactively, from a user's standpoint.
+
+* Menu:
+
+* History Interaction:: What it feels like using History as a user.
+
+
+File: gdb.info, Node: History Interaction, Up: Using History Interactively
+
+History Interaction
+===================
+
+ The History library provides a history expansion feature that is
+similar to the history expansion in Csh. The following text describes
+the sytax that you use to manipulate the history information.
+
+ 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 "event", and the portions of that line that are
+acted upon are called "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.
+
+
+File: gdb.info, Node: Event Designators, Next: Word Designators, Up: History Interaction
+
+Event Designators
+-----------------
+
+ An event designator is a reference to a command line entry in the
+history list.
+
+`!'
+ Start a history subsititution, except when followed by a space,
+ tab, or the end of the line... = or (.
+
+`!!'
+ Refer to the previous command. This is a synonym for `!-1'.
+
+`!n'
+ Refer to command line N.
+
+`!-n'
+ Refer to the command line N lines back.
+
+`!string'
+ Refer to the most recent command starting with STRING.
+
+`!?string'[`?']
+ Refer to the most recent command containing STRING.
+
+
+File: gdb.info, Node: Word Designators, Next: Modifiers, Prev: Event Designators, Up: History Interaction
+
+Word Designators
+----------------
+
+ A : separates the event specification from the word designator. It
+can be omitted if the word designator begins with a ^, $, * or %.
+Words are numbered from the beginning of the line, with the first word
+being denoted by a 0 (zero).
+
+`0 (zero)'
+ The zero'th word. For many applications, this is the command word.
+
+`n'
+ The N'th word.
+
+`^'
+ The first argument. that is, word 1.
+
+`$'
+ The last argument.
+
+`%'
+ The word matched by the most recent `?string?' search.
+
+`x-y'
+ A range of words; `-Y' Abbreviates `0-Y'.
+
+`*'
+ All of the words, excepting the zero'th. This is a synonym for
+ `1-$'. It is not an error to use * if there is just one word in
+ the event. The empty string is returned in that case.
+
+
+File: gdb.info, Node: Modifiers, Prev: Word Designators, Up: History Interaction
+
+Modifiers
+---------
+
+ After the optional word designator, you can add a sequence of one or
+more of the following modifiers, each preceded by a :.
+
+`#'
+ 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.
+
+`h'
+ Remove a trailing pathname component, leaving only the head.
+
+`r'
+ Remove a trailing suffix of the form `.'SUFFIX, leaving the
+ basename.
+
+`e'
+ Remove all but the suffix.
+
+`t'
+ Remove all leading pathname components, leaving the tail.
+
+`p'
+ Print the new command but do not execute it.
+
+
+File: gdb.info, Node: Renamed Commands, Next: Formatting Documentation, Prev: Using History Interactively, Up: Top
+
+Renamed Commands
+****************
+
+ The following commands were renamed in GDB 4, in order to make the
+command set as a whole more consistent and easier to use and remember:
+
+ OLD COMMAND NEW COMMAND
+ --------------- -------------------------------
+ add-syms add-symbol-file
+ delete environment unset environment
+ info convenience show convenience
+ info copying show copying
+ info directories show directories
+ info editing show commands
+ info history show values
+ info targets help target
+ info values show values
+ info version show version
+ info warranty show warranty
+ set/show addressprint set/show print address
+ set/show array-max set/show print elements
+ set/show arrayprint set/show print array
+ set/show asm-demangle set/show print asm-demangle
+ set/show caution set/show confirm
+ set/show demangle set/show print demangle
+ set/show history write set/show history save
+ set/show prettyprint set/show print pretty
+ set/show screen-height set/show height
+ set/show screen-width set/show width
+ set/show sevenbit-strings set/show print sevenbit-strings
+ set/show unionprint set/show print union
+ set/show vtblprint set/show print vtbl
+
+ unset [No longer an alias for delete]
+
+
+File: gdb.info, Node: Formatting Documentation, Next: Installing GDB, Prev: Renamed Commands, Up: Top
+
+Formatting Documentation
+************************
+
+ The GDB 4 release includes an already-formatted reference card, ready
+for printing with PostScript or GhostScript, in the `gdb' subdirectory
+of the main source directory(1). If you can use PostScript or
+GhostScript with your printer, you can print the reference card
+immediately with `refcard.ps'.
+
+ The release also includes the source for the reference card. You
+can format it, using TeX, by typing:
+
+ make refcard.dvi
+
+ The GDB reference card is designed to print in landscape mode on US
+"letter" size paper; that is, on a sheet 11 inches wide by 8.5 inches
+high. You will need to specify this form of printing as an option to
+your DVI output program.
+
+ All the documentation for GDB comes as part of the machine-readable
+distribution. The documentation is written in Texinfo format, which is
+a documentation system that uses a single source file to produce both
+on-line information and a printed manual. You can use one of the Info
+formatting commands to create the on-line version of the documentation
+and TeX (or `texi2roff') to typeset the printed version.
+
+ GDB includes an already formatted copy of the on-line Info version of
+this manual in the `gdb' subdirectory. The main Info file is
+`gdb-VERSION-NUMBER/gdb/gdb.info', and it refers to subordinate files
+matching `gdb.info*' in the same directory. If necessary, you can
+print out these files, or read them with any editor; but they are
+easier to read using the `info' subsystem in GNU Emacs or the
+standalone `info' program, available as part of the GNU Texinfo
+distribution.
+
+ If you want to format these Info files yourself, you need one of the
+Info formatting programs, such as `texinfo-format-buffer' or `makeinfo'.
+
+ If you have `makeinfo' installed, and are in the top level GDB
+source directory (`gdb-4.11', in the case of version 4.11), you can
+make the Info file by typing:
+
+ cd gdb
+ make gdb.info
+
+ If you want to typeset and print copies of this manual, you need TeX,
+a program to print its DVI output files, and `texinfo.tex', the Texinfo
+definitions file.
+
+ TeX is a typesetting program; it does not print files directly, but
+produces output files called DVI files. To print a typeset document,
+you need a program to print DVI files. If your system has TeX
+installed, chances are it has such a program. The precise command to
+use depends on your system; `lpr -d' is common; another (for PostScript
+devices) is `dvips'. The DVI print command may require a file name
+without any extension or a `.dvi' extension.
+
+ TeX also requires a macro definitions file called `texinfo.tex'.
+This file tells TeX how to typeset a document written in Texinfo
+format. On its own, TeX cannot read, much less typeset a Texinfo file.
+`texinfo.tex' is distributed with GDB and is located in the
+`gdb-VERSION-NUMBER/texinfo' directory.
+
+ If you have TeX and a DVI printer program installed, you can typeset
+and print this manual. First switch to the the `gdb' subdirectory of
+the main source directory (for example, to `gdb-4.11/gdb') and then
+type:
+
+ make gdb.dvi
+
+ ---------- Footnotes ----------
+
+ (1) In `gdb-4.11/gdb/refcard.ps' of the version 4.11 release.
+
+
+File: gdb.info, Node: Installing GDB, Next: Index, Prev: Formatting Documentation, Up: Top
+
+Installing GDB
+**************
+
+ GDB comes with a `configure' script that automates the process of
+preparing GDB for installation; you can then use `make' to build the
+`gdb' program.
+
+ The GDB distribution includes all the source code you need for GDB in
+a single directory, whose name is usually composed by appending the
+version number to `gdb'.
+
+ For example, the GDB version 4.11 distribution is in the `gdb-4.11'
+directory. That directory contains:
+
+`gdb-4.11/configure (and supporting files)'
+ script for configuring GDB and all its supporting libraries.
+
+`gdb-4.11/gdb'
+ the source specific to GDB itself
+
+`gdb-4.11/bfd'
+ source for the Binary File Descriptor library
+
+`gdb-4.11/include'
+ GNU include files
+
+`gdb-4.11/libiberty'
+ source for the `-liberty' free software library
+
+`gdb-4.11/opcodes'
+ source for the library of opcode tables and disassemblers
+
+`gdb-4.11/readline'
+ source for the GNU command-line interface
+
+`gdb-4.11/glob'
+ source for the GNU filename pattern-matching subroutine
+
+`gdb-4.11/mmalloc'
+ source for the GNU memory-mapped malloc package
+
+ The simplest way to configure and build GDB is to run `configure'
+from the `gdb-VERSION-NUMBER' source directory, which in this example
+is the `gdb-4.11' directory.
+
+ First switch to the `gdb-VERSION-NUMBER' source directory if you are
+not already in it; then run `configure'. Pass the identifier for the
+platform on which GDB will run as an argument.
+
+ For example:
+
+ cd gdb-4.11
+ ./configure HOST
+ make
+
+where HOST is an identifier such as `sun4' or `decstation', that
+identifies the platform where GDB will run. (You can often leave off
+HOST; `configure' tries to guess the correct value by examining your
+system.)
+
+ Running `configure HOST' and then running `make' builds the `bfd',
+`readline', `mmalloc', and `libiberty' libraries, then `gdb' itself.
+The configured source files, and the binaries, are left in the
+corresponding source directories.
+
+ `configure' is a Bourne-shell (`/bin/sh') script; if your system
+does not recognize this automatically when you run a different shell,
+you may need to run `sh' on it explicitly:
+
+ sh configure HOST
+
+ If you run `configure' from a directory that contains source
+directories for multiple libraries or programs, such as the `gdb-4.11'
+source directory for version 4.11, `configure' creates configuration
+files for every directory level underneath (unless you tell it not to,
+with the `--norecursion' option).
+
+ You can run the `configure' script from any of the subordinate
+directories in the GDB distribution if you only want to configure that
+subdirectory, but be sure to specify a path to it.
+
+ For example, with version 4.11, type the following to configure only
+the `bfd' subdirectory:
+
+ cd gdb-4.11/bfd
+ ../configure HOST
+
+ You can install `gdb' anywhere; it has no hardwired paths. However,
+you should make sure that the shell on your path (named by the `SHELL'
+environment variable) is publicly readable. Remember that GDB uses the
+shell to start your program--some systems refuse to let GDB debug child
+processes whose programs are not readable.
+
+* Menu:
+
+* Separate Objdir:: Compiling GDB in another directory
+* Config Names:: Specifying names for hosts and targets
+* configure Options:: Summary of options for configure
+
+
+File: gdb.info, Node: Separate Objdir, Next: Config Names, Up: Installing GDB
+
+Compiling GDB in another directory
+==================================
+
+ If you want to run GDB versions for several host or target machines,
+you need a different `gdb' compiled for each combination of host and
+target. `configure' is designed to make this easy by allowing you to
+generate each configuration in a separate subdirectory, rather than in
+the source directory. If your `make' program handles the `VPATH'
+feature (GNU `make' does), running `make' in each of these directories
+builds the `gdb' program specified there.
+
+ To build `gdb' in a separate directory, run `configure' with the
+`--srcdir' option to specify where to find the source. (You also need
+to specify a path to find `configure' itself from your working
+directory. If the path to `configure' would be the same as the
+argument to `--srcdir', you can leave out the `--srcdir' option; it
+will be assumed.)
+
+ For example, with version 4.11, you can build GDB in a separate
+directory for a Sun 4 like this:
+
+ cd gdb-4.11
+ mkdir ../gdb-sun4
+ cd ../gdb-sun4
+ ../gdb-4.11/configure sun4
+ make
+
+ When `configure' builds a configuration using a remote source
+directory, it creates a tree for the binaries with the same structure
+(and using the same names) as the tree under the source directory. In
+the example, you'd find the Sun 4 library `libiberty.a' in the
+directory `gdb-sun4/libiberty', and GDB itself in `gdb-sun4/gdb'.
+
+ One popular reason to build several GDB configurations in separate
+directories is to configure GDB for cross-compiling (where GDB runs on
+one machine--the host--while debugging programs that run on another
+machine--the target). You specify a cross-debugging target by giving
+the `--target=TARGET' option to `configure'.
+
+ When you run `make' to build a program or library, you must run it
+in a configured directory--whatever directory you were in when you
+called `configure' (or one of its subdirectories).
+
+ The `Makefile' that `configure' generates in each source directory
+also runs recursively. If you type `make' in a source directory such
+as `gdb-4.11' (or in a separate configured directory configured with
+`--srcdir=PATH/gdb-4.11'), you will build all the required libraries,
+and then build GDB.
+
+ When you have multiple hosts or targets configured in separate
+directories, you can run `make' on them in parallel (for example, if
+they are NFS-mounted on each of the hosts); they will not interfere
+with each other.
+
+
+File: gdb.info, Node: Config Names, Next: configure Options, Prev: Separate Objdir, Up: Installing GDB
+
+Specifying names for hosts and targets
+======================================
+
+ The specifications used for hosts and targets in the `configure'
+script are based on a three-part naming scheme, but some short
+predefined aliases are also supported. The full naming scheme encodes
+three pieces of information in the following pattern:
+
+ ARCHITECTURE-VENDOR-OS
+
+ For example, you can use the alias `sun4' as a HOST argument, or as
+the value for TARGET in a `--target=TARGET' option. The equivalent
+full name is `sparc-sun-sunos4'.
+
+ The `configure' script accompanying GDB does not provide any query
+facility to list all supported host and target names or aliases.
+`configure' calls the Bourne shell script `config.sub' to map
+abbreviations to full names; you can read the script, if you wish, or
+you can use it to test your guesses on abbreviations--for example:
+
+ % sh config.sub sun4
+ sparc-sun-sunos4.1.1
+ % sh config.sub sun3
+ m68k-sun-sunos4.1.1
+ % sh config.sub decstation
+ mips-dec-ultrix4.2
+ % sh config.sub hp300bsd
+ m68k-hp-bsd
+ % sh config.sub i386v
+ i386-unknown-sysv
+ % sh config.sub i786v
+ Invalid configuration `i786v': machine `i786v' not recognized
+
+`config.sub' is also distributed in the GDB source directory
+(`gdb-4.11', for version 4.11).
+
+
+File: gdb.info, Node: configure Options, Prev: Config Names, Up: Installing GDB
+
+`configure' options
+===================
+
+ Here is a summary of the `configure' options and arguments that are
+most often useful for building GDB. `configure' also has several other
+options not listed here. *note : (configure.info)What Configure Does,
+for a full explanation of `configure'.
+
+ configure [--help]
+ [--prefix=DIR]
+ [--srcdir=PATH]
+ [--norecursion] [--rm]
+ [--target=TARGET] HOST
+
+You may introduce options with a single `-' rather than `--' if you
+prefer; but you may abbreviate option names if you use `--'.
+
+`--help'
+ Display a quick summary of how to invoke `configure'.
+
+`-prefix=DIR'
+ Configure the source to install programs and files under directory
+ `DIR'.
+
+`--srcdir=PATH'
+ *Warning: using this option requires GNU `make', or another `make'
+ that implements the `VPATH' feature.*
+ Use this option to make configurations in directories separate
+ from the GDB source directories. Among other things, you can use
+ this to build (or maintain) several configurations simultaneously,
+ in separate directories. `configure' writes configuration
+ specific files in the current directory, but arranges for them to
+ use the source in the directory PATH. `configure' will create
+ directories under the working directory in parallel to the source
+ directories below PATH.
+
+`--norecursion'
+ Configure only the directory level where `configure' is executed;
+ do not propagate configuration to subdirectories.
+
+`--rm'
+ *Remove* files otherwise built during configuration.
+
+`--target=TARGET'
+ Configure GDB for cross-debugging programs running on the specified
+ TARGET. Without this option, GDB is configured to debug programs
+ that run on the same machine (HOST) as GDB itself.
+
+ There is no convenient way to generate a list of all available
+ targets.
+
+`HOST ...'
+ Configure GDB to run on the specified HOST.
+
+ There is no convenient way to generate a list of all available
+ hosts.
+
+`configure' accepts other options, for compatibility with configuring
+other GNU tools recursively; but these are the only options that affect
+GDB or its supporting libraries.
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.info-8 b/gnu/usr.bin/gdb/doc/gdb.info-8
new file mode 100644
index 000000000000..1d259e043236
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.info-8
@@ -0,0 +1,657 @@
+This is Info file ./gdb.info, produced by Makeinfo-1.52 from the input
+file gdb.texinfo.
+
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+ This file documents the GNU debugger GDB.
+
+ This is Edition 4.09, August 1993, of `Debugging with GDB: the GNU
+Source-Level Debugger' for GDB Version 4.11.
+
+ Copyright (C) 1988, '89, '90, '91, '92, '93 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.
+
+
+File: gdb.info, Node: Index, Prev: Installing GDB, Up: Top
+
+Index
+*****
+
+* Menu:
+
+* #: Command Syntax.
+* $bpnum: Set Breaks.
+* $cdir: Source Path.
+* $cwd: Source Path.
+* $_: Convenience Vars.
+* $__: Convenience Vars.
+* .: M2 Scope.
+* .esgdbinit: Command Files.
+* .os68gdbinit: Command Files.
+* .vxgdbinit: Command Files.
+* /proc: Process Information.
+* 386: Remote Serial.
+* 680x0: Remote Serial.
+* @: Arrays.
+* # in Modula-2: GDB/M2.
+* $$: Value History.
+* $_ and info breakpoints: Set Breaks.
+* $_ and info line: Machine Code.
+* $_, $__, and value history: Memory.
+* $: Value History.
+* breakpoint subroutine, remote: Stub Contents.
+* heuristic-fence-post (MIPS): MIPS Stack.
+* remotedebug, MIPS protocol: MIPS Remote.
+* retransmit-timeout, MIPS protocol: MIPS Remote.
+* timeout, MIPS protocol: MIPS Remote.
+* vi style command editing: Readline Vi Mode.
+* .gdbinit: Command Files.
+* COFF versus C++: Cplus expressions.
+* ECOFF and C++: Cplus expressions.
+* ELF/DWARF and C++: Cplus expressions.
+* ELF/stabs and C++: Cplus expressions.
+* XCOFF and C++: Cplus expressions.
+* GDB bugs, reporting: Bug Reporting.
+* {TYPE}: Expressions.
+* a.out and C++: Cplus expressions.
+* abbreviation: Command Syntax.
+* active targets: Active Targets.
+* add-symbol-file: Files.
+* add-syms: Renamed Commands.
+* AMD 29K register stack: Registers.
+* AMD EB29K: Target Commands.
+* AMD29K via UDI: UDI29K Remote.
+* arguments (to your program): Arguments.
+* artificial array: Arrays.
+* assembly instructions: Machine Code.
+* assignment: Assignment.
+* attach: Attach.
+* attach: Attach.
+* automatic display: Auto Display.
+* b: Set Breaks.
+* backtrace: Backtrace.
+* break: Set Breaks.
+* break in overloaded functions: Debugging C plus plus.
+* breakpoint commands: Break Commands.
+* breakpoint conditions: Conditions.
+* breakpoint numbers: Breakpoints.
+* breakpoint on memory address: Breakpoints.
+* breakpoint on variable modification: Breakpoints.
+* breakpoints: Breakpoints.
+* bt: Backtrace.
+* bug criteria: Bug Criteria.
+* bug reports: Bug Reporting.
+* bugs in GDB: GDB Bugs.
+* c: Continuing and Stepping.
+* C and C++: C.
+* C and C++ checks: C Checks.
+* C and C++ constants: C Operators.
+* C and C++ defaults: C Defaults.
+* C and C++ operators: C.
+* C++: C.
+* C++ and object formats: Cplus expressions.
+* C++ exception handling: Debugging C plus plus.
+* C++ scope resolution: Variables.
+* C++ support, not in COFF: Cplus expressions.
+* C++ symbol decoding style: Print Settings.
+* C++ symbol display: Debugging C plus plus.
+* call: Calling.
+* call overloaded functions: Cplus expressions.
+* call stack: Stack.
+* calling functions: Calling.
+* calling make: Shell Commands.
+* casts, to view memory: Expressions.
+* catch: Exception Handling.
+* catch exceptions: Frame Info.
+* cd: Working Directory.
+* cdir: Source Path.
+* checks, range: Type Checking.
+* checks, type: Checks.
+* checksum, for GDB remote: Protocol.
+* clear: Delete Breaks.
+* clearing breakpoints, watchpoints: Delete Breaks.
+* colon, doubled as scope operator: M2 Scope.
+* colon-colon: M2 Scope.
+* colon-colon: Variables.
+* command files: Hooks.
+* command files: Command Files.
+* command line editing: Editing.
+* commands: Break Commands.
+* commands for C++: Debugging C plus plus.
+* commands to STDBUG (ST2000): ST2000 Remote.
+* comment: Command Syntax.
+* compilation directory: Source Path.
+* completion: Completion.
+* completion of quoted strings: Completion.
+* condition: Conditions.
+* conditional breakpoints: Conditions.
+* configuring GDB: Installing GDB.
+* confirmation: Messages/Warnings.
+* connect (to STDBUG): ST2000 Remote.
+* continue: Continuing and Stepping.
+* continuing: Continuing and Stepping.
+* controlling terminal: Input/Output.
+* convenience variables: Convenience Vars.
+* core: Files.
+* core dump file: Files.
+* core-file: Files.
+* CPU simulator: Simulator.
+* crash of debugger: Bug Criteria.
+* current directory: Source Path.
+* cwd: Source Path.
+* d: Delete Breaks.
+* debugger crash: Bug Criteria.
+* debugging optimized code: Compilation.
+* debugging stub, example: Protocol.
+* debugging target: Targets.
+* define: Define.
+* delete: Delete Breaks.
+* delete breakpoints: Delete Breaks.
+* delete display: Auto Display.
+* delete environment: Renamed Commands.
+* deleting breakpoints, watchpoints: Delete Breaks.
+* detach: Attach.
+* device: Hitachi Remote.
+* directories for source files: Source Path.
+* directory: Source Path.
+* directory, compilation: Source Path.
+* directory, current: Source Path.
+* dis: Disabling.
+* disable: Disabling.
+* disable breakpoints: Disabling.
+* disable display: Auto Display.
+* disabled breakpoints: Disabling.
+* disassemble: Machine Code.
+* display: Auto Display.
+* display of expressions: Auto Display.
+* do: Selection.
+* document: Define.
+* documentation: Formatting Documentation.
+* down: Selection.
+* down-silently: Selection.
+* download to H8/300 or H8/500: Files.
+* download to Hitachi SH: Files.
+* download to Nindy-960: Files.
+* download to VxWorks: VxWorks Download.
+* dynamic linking: Files.
+* eb.log: Remote Log.
+* EB29K board: EB29K Remote.
+* EBMON: Comms (EB29K).
+* echo: Output.
+* editing: Editing.
+* editing-mode: Readline Init Syntax.
+* emacs: Emacs.
+* enable: Disabling.
+* enable breakpoints: Disabling.
+* enable display: Auto Display.
+* enabled breakpoints: Disabling.
+* end: Break Commands.
+* entering numbers: Numbers.
+* environment (of your program): Environment.
+* error on valid input: Bug Criteria.
+* event designators: Event Designators.
+* examining data: Data.
+* examining memory: Memory.
+* exception handlers: Exception Handling.
+* exception handlers: Frame Info.
+* exceptionHandler: Bootstrapping.
+* exec-file: Files.
+* executable file: Files.
+* exiting GDB: Quitting GDB.
+* expansion: History Interaction.
+* expressions: Expressions.
+* expressions in C or C++: C.
+* expressions in C++: Cplus expressions.
+* expressions in Modula-2: Modula-2.
+* f: Selection.
+* fatal signal: Bug Criteria.
+* fatal signals: Signals.
+* fg: Continuing and Stepping.
+* file: Files.
+* finish: Continuing and Stepping.
+* flinching: Messages/Warnings.
+* floating point: Floating Point Hardware.
+* floating point registers: Registers.
+* floating point, MIPS remote: MIPS Remote.
+* flush_i_cache: Bootstrapping.
+* foo: Symbol Errors.
+* format options: Print Settings.
+* formatted output: Output Formats.
+* Fortran: Summary.
+* forward-search: Search.
+* frame: Selection.
+* frame: Frames.
+* frame number: Frames.
+* frame pointer: Frames.
+* frameless execution: Frames.
+* g++: C.
+* GDB reference card: Formatting Documentation.
+* gdbserver: Server.
+* getDebugChar: Bootstrapping.
+* GNU C++: C.
+* h: Help.
+* H8/300 or H8/500 download: Files.
+* H8/300 or H8/500 simulator: Simulator.
+* handle: Signals.
+* handle_exception: Stub Contents.
+* handling signals: Signals.
+* help: Help.
+* help target: Target Commands.
+* help user-defined: Define.
+* history expansion: History.
+* history file: History.
+* history number: Value History.
+* history save: History.
+* history size: History.
+* history substitution: History.
+* Hitachi SH download: Files.
+* Hitachi SH simulator: Simulator.
+* horizontal-scroll-mode: Readline Init Syntax.
+* i: Help.
+* i/o: Input/Output.
+* i386-stub.c: Remote Serial.
+* i960: i960-Nindy Remote.
+* ignore: Conditions.
+* ignore count (of breakpoint): Conditions.
+* INCLUDE_RDB: VxWorks Remote.
+* info: Help.
+* info address: Symbols.
+* info all-registers: Registers.
+* info args: Frame Info.
+* info breakpoints: Set Breaks.
+* info catch: Frame Info.
+* info convenience: Renamed Commands.
+* info copying: Renamed Commands.
+* info directories: Renamed Commands.
+* info display: Auto Display.
+* info editing: Renamed Commands.
+* info f: Frame Info.
+* info files: Files.
+* info float: Floating Point Hardware.
+* info frame: Frame Info.
+* info frame: Show.
+* info functions: Symbols.
+* info history: Renamed Commands.
+* info line: Machine Code.
+* info locals: Frame Info.
+* info proc: Process Information.
+* info proc id: Process Information.
+* info proc mappings: Process Information.
+* info proc status: Process Information.
+* info proc times: Process Information.
+* info program: Stopping.
+* info registers: Registers.
+* info s: Backtrace.
+* info set: Help.
+* info share: Files.
+* info sharedlibrary: Files.
+* info signals: Signals.
+* info source: Symbols.
+* info source: Show.
+* info sources: Symbols.
+* info stack: Backtrace.
+* info target: Files.
+* info targets: Renamed Commands.
+* info terminal: Input/Output.
+* info types: Symbols.
+* info values: Renamed Commands.
+* info variables: Symbols.
+* info version: Renamed Commands.
+* info warranty: Renamed Commands.
+* info watchpoints: Set Watchpoints.
+* inheritance: Debugging C plus plus.
+* init file: Command Files.
+* init file name: Command Files.
+* initial frame: Frames.
+* innermost frame: Frames.
+* inspect: Data.
+* installation: Installing GDB.
+* instructions, assembly: Machine Code.
+* Intel: Remote Serial.
+* interaction, readline: Readline Interaction.
+* internal GDB breakpoints: Set Breaks.
+* interrupt: Quitting GDB.
+* interrupting remote programs: Debug Session.
+* invalid input: Bug Criteria.
+* jump: Jumping.
+* kill: Kill Process.
+* l: List.
+* languages: Languages.
+* latest breakpoint: Set Breaks.
+* leaving GDB: Quitting GDB.
+* linespec: List.
+* list: List.
+* listing machine instructions: Machine Code.
+* load: Files.
+* log file for EB29K: Remote Log.
+* m68k-stub.c: Remote Serial.
+* machine instructions: Machine Code.
+* maint info breakpoints: Set Breaks.
+* maint print psymbols: Symbols.
+* maint print symbols: Symbols.
+* make: Shell Commands.
+* mapped: Files.
+* mark-modified-lines: Readline Init Syntax.
+* member functions: Cplus expressions.
+* memory tracing: Breakpoints.
+* memory, viewing as typed object: Expressions.
+* memory-mapped symbol file: Files.
+* memset: Bootstrapping.
+* MIPS boards: MIPS Remote.
+* MIPS remote floating point: MIPS Remote.
+* MIPS stack: MIPS Stack.
+* Modula-2: Modula-2.
+* Modula-2 built-ins: M2 Operators.
+* Modula-2 checks: M2 Checks.
+* Modula-2 constants: Built-In Func/Proc.
+* Modula-2 defaults: M2 Defaults.
+* Modula-2 operators: M2 Operators.
+* Modula-2, deviations from: Deviations.
+* Motorola 680x0: Remote Serial.
+* multiple targets: Active Targets.
+* n: Continuing and Stepping.
+* names of symbols: Symbols.
+* namespace in C++: Cplus expressions.
+* negative breakpoint numbers: Set Breaks.
+* next: Continuing and Stepping.
+* nexti: Continuing and Stepping.
+* ni: Continuing and Stepping.
+* Nindy: i960-Nindy Remote.
+* number representation: Numbers.
+* numbers for breakpoints: Breakpoints.
+* object formats and C++: Cplus expressions.
+* online documentation: Help.
+* optimized code, debugging: Compilation.
+* outermost frame: Frames.
+* output: Output.
+* output formats: Output Formats.
+* overloading: Breakpoint Menus.
+* overloading in C++: Debugging C plus plus.
+* packets, reporting on stdout: Protocol.
+* partial symbol dump: Symbols.
+* patching binaries: Patching.
+* path: Environment.
+* pauses in output: Screen Size.
+* pipes: Starting.
+* prefer-visible-bell: Readline Init Syntax.
+* print: Data.
+* print settings: Print Settings.
+* printf: Output.
+* printing data: Data.
+* process image: Process Information.
+* prompt: Prompt.
+* protocol, GDB remote serial: Protocol.
+* ptype: Symbols.
+* putDebugChar: Bootstrapping.
+* pwd: Working Directory.
+* q: Quitting GDB.
+* quit: Quitting GDB.
+* quotes in commands: Completion.
+* quoting names: Symbols.
+* raise exceptions: Exception Handling.
+* range checking: Type Checking.
+* rbreak: Set Breaks.
+* reading symbols immediately: Files.
+* readline: Editing.
+* readnow: Files.
+* redirection: Input/Output.
+* reference card: Formatting Documentation.
+* reference declarations: Cplus expressions.
+* register stack, AMD29K: Registers.
+* registers: Registers.
+* regular expression: Set Breaks.
+* reloading symbols: Messages/Warnings.
+* remote connection without stubs: Server.
+* remote debugging: Remote.
+* remote programs, interrupting: Debug Session.
+* remote serial debugging summary: Debug Session.
+* remote serial debugging, overview: Remote Serial.
+* remote serial protocol: Protocol.
+* remote serial stub: Stub Contents.
+* remote serial stub list: Remote Serial.
+* remote serial stub, initialization: Stub Contents.
+* remote serial stub, main routine: Stub Contents.
+* remote stub, example: Protocol.
+* remote stub, support routines: Bootstrapping.
+* repeating commands: Command Syntax.
+* reporting bugs in GDB: GDB Bugs.
+* reset: Nindy Reset.
+* response time, MIPS debugging: MIPS Stack.
+* resuming execution: Continuing and Stepping.
+* RET: Command Syntax.
+* return: Returning.
+* returning from a function: Returning.
+* reverse-search: Search.
+* run: Starting.
+* running: Starting.
+* running 29K programs: EB29K Remote.
+* running VxWorks tasks: VxWorks Attach.
+* s: Continuing and Stepping.
+* saving symbol table: Files.
+* scope: M2 Scope.
+* search: Search.
+* searching: Search.
+* selected frame: Stack.
+* serial connections, debugging: Protocol.
+* serial device, Hitachi micros: Hitachi Remote.
+* serial line speed, Hitachi micros: Hitachi Remote.
+* serial line, target remote: Debug Session.
+* serial protocol, GDB remote: Protocol.
+* set addressprint: Renamed Commands.
+* set args: Arguments.
+* set array-max: Renamed Commands.
+* set arrayprint: Renamed Commands.
+* set asm-demangle: Renamed Commands.
+* set caution: Renamed Commands.
+* set check: Range Checking.
+* set check: Type Checking.
+* set check range: Range Checking.
+* set check type: Type Checking.
+* set complaints: Messages/Warnings.
+* set confirm: Messages/Warnings.
+* set demangle: Renamed Commands.
+* set demangle-style: Print Settings.
+* set editing: Editing.
+* set environment: Environment.
+* set height: Screen Size.
+* set history expansion: History.
+* set history filename: History.
+* set history save: History.
+* set history size: History.
+* set history write: Renamed Commands.
+* set language: Manually.
+* set listsize: List.
+* set mipsfpu off: MIPS Remote.
+* set prettyprint: Renamed Commands.
+* set print address: Print Settings.
+* set print array: Print Settings.
+* set print asm-demangle: Print Settings.
+* set print demangle: Print Settings.
+* set print elements: Print Settings.
+* set print max-symbolic-offset: Print Settings.
+* set print object: Print Settings.
+* set print pretty: Print Settings.
+* set print sevenbit-strings: Print Settings.
+* set print symbol-filename: Print Settings.
+* set print union: Print Settings.
+* set print vtbl: Print Settings.
+* set prompt: Prompt.
+* set radix: Numbers.
+* set remotedebug: Protocol.
+* set retransmit-timeout: MIPS Remote.
+* set rstack_high_address: Registers.
+* set screen-height: Renamed Commands.
+* set screen-width: Renamed Commands.
+* set sevenbit-strings: Renamed Commands.
+* set symbol-reloading: Messages/Warnings.
+* set timeout: MIPS Remote.
+* set unionprint: Renamed Commands.
+* set variable: Assignment.
+* set verbose: Messages/Warnings.
+* set vtblprint: Renamed Commands.
+* set width: Screen Size.
+* set write: Patching.
+* setting variables: Assignment.
+* setting watchpoints: Set Watchpoints.
+* set_debug_traps: Stub Contents.
+* share: Files.
+* shared libraries: Files.
+* sharedlibrary: Files.
+* shell: Shell Commands.
+* shell escape: Shell Commands.
+* show: Help.
+* show addressprint: Renamed Commands.
+* show args: Arguments.
+* show array-max: Renamed Commands.
+* show arrayprint: Renamed Commands.
+* show asm-demangle: Renamed Commands.
+* show caution: Renamed Commands.
+* show check range: Range Checking.
+* show check type: Type Checking.
+* show commands: History.
+* show complaints: Messages/Warnings.
+* show confirm: Messages/Warnings.
+* show convenience: Convenience Vars.
+* show copying: Help.
+* show demangle: Renamed Commands.
+* show demangle-style: Print Settings.
+* show directories: Source Path.
+* show editing: Editing.
+* show environment: Environment.
+* show height: Screen Size.
+* show history: History.
+* show history write: Renamed Commands.
+* show language: Show.
+* show listsize: List.
+* show paths: Environment.
+* show prettyprint: Renamed Commands.
+* show print address: Print Settings.
+* show print array: Print Settings.
+* show print asm-demangle: Print Settings.
+* show print demangle: Print Settings.
+* show print elements: Print Settings.
+* show print max-symbolic-offset: Print Settings.
+* show print object: Print Settings.
+* show print pretty: Print Settings.
+* show print sevenbit-strings: Print Settings.
+* show print symbol-filename: Print Settings.
+* show print union: Print Settings.
+* show print vtbl: Print Settings.
+* show prompt: Prompt.
+* show radix: Numbers.
+* show remotedebug: Protocol.
+* show retransmit-timeout: MIPS Remote.
+* show rstack_high_address: Registers.
+* show screen-height: Renamed Commands.
+* show screen-width: Renamed Commands.
+* show sevenbit-strings: Renamed Commands.
+* show timeout: MIPS Remote.
+* show unionprint: Renamed Commands.
+* show user: Define.
+* show values: Value History.
+* show verbose: Messages/Warnings.
+* show version: Help.
+* show vtblprint: Renamed Commands.
+* show warranty: Help.
+* show width: Screen Size.
+* show write: Patching.
+* si: Continuing and Stepping.
+* signal: Signaling.
+* signals: Signals.
+* silent: Break Commands.
+* sim: Simulator.
+* simulator: Simulator.
+* simulator, H8/300 or H8/500: Simulator.
+* simulator, Hitachi SH: Simulator.
+* simulator, Z8000: Simulator.
+* size of screen: Screen Size.
+* source: Command Files.
+* source path: Source Path.
+* sparc-stub.c: Remote Serial.
+* speed: Hitachi Remote.
+* st2000 CMD: ST2000 Remote.
+* ST2000 auxiliary commands: ST2000 Remote.
+* stack frame: Frames.
+* stack on MIPS: MIPS Stack.
+* stacking targets: Active Targets.
+* starting: Starting.
+* STDBUG commands (ST2000): ST2000 Remote.
+* step: Continuing and Stepping.
+* stepi: Continuing and Stepping.
+* stepping: Continuing and Stepping.
+* stub example, remote debugging: Protocol.
+* stupid questions: Messages/Warnings.
+* symbol decoding style, C++: Print Settings.
+* symbol dump: Symbols.
+* symbol names: Symbols.
+* symbol overloading: Breakpoint Menus.
+* symbol table: Files.
+* symbol-file: Files.
+* symbols, reading immediately: Files.
+* target: Targets.
+* target amd-eb: Target Commands.
+* target core: Target Commands.
+* target exec: Target Commands.
+* target hms: Target Commands.
+* target mips PORT: MIPS Remote.
+* target nindy: Target Commands.
+* target remote: Target Commands.
+* target sim: Target Commands.
+* target sim: Simulator.
+* target st2000: Target Commands.
+* target udi: Target Commands.
+* target vxworks: Target Commands.
+* tbreak: Set Breaks.
+* TCP port, target remote: Debug Session.
+* terminal: Input/Output.
+* this: Cplus expressions.
+* toggle-editing-mode: Readline Vi Mode.
+* tty: Input/Output.
+* type casting memory: Expressions.
+* type checking: Checks.
+* type conversions in C++: Cplus expressions.
+* u: Continuing and Stepping.
+* udi: UDI29K Remote.
+* UDI: UDI29K Remote.
+* undisplay: Auto Display.
+* unset: Renamed Commands.
+* unset environment: Environment.
+* until: Continuing and Stepping.
+* up: Selection.
+* up-silently: Selection.
+* user-defined command: Define.
+* value history: Value History.
+* variable name conflict: Variables.
+* variable values, wrong: Variables.
+* variables, setting: Assignment.
+* version number: Help.
+* VxWorks: VxWorks Remote.
+* watch: Set Watchpoints.
+* watchpoints: Breakpoints.
+* whatis: Symbols.
+* where: Backtrace.
+* word completion: Completion.
+* working directory: Source Path.
+* working directory (of your program): Working Directory.
+* working language: Languages.
+* writing into corefiles: Patching.
+* writing into executables: Patching.
+* wrong values: Variables.
+* x: Memory.
+* Z8000 simulator: Simulator.
+
+
diff --git a/gnu/usr.bin/gdb/doc/gdb.texinfo b/gnu/usr.bin/gdb/doc/gdb.texinfo
new file mode 100644
index 000000000000..a2f293deb2a8
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdb.texinfo
@@ -0,0 +1,8591 @@
+\input texinfo @c -*-texinfo-*-
+@c Copyright (c) 1988 1989 1990 1991 1992 1993 Free Software Foundation, Inc.
+@c
+@c %**start of header
+@c makeinfo ignores cmds prev to setfilename, so its arg cannot make use
+@c of @set vars. However, you can override filename with makeinfo -o.
+@setfilename gdb.info
+@c
+@include gdb-cfg.texi
+@c
+@ifset GENERIC
+@settitle Debugging with @value{GDBN}
+@end ifset
+@ifclear GENERIC
+@settitle Debugging with @value{GDBN} (@value{TARGET})
+@end ifclear
+@setchapternewpage odd
+@c %**end of header
+
+@iftex
+@c @smallbook
+@c @cropmarks
+@end iftex
+
+@finalout
+@syncodeindex ky cp
+
+@c readline appendices use @vindex
+@syncodeindex vr cp
+
+@c ===> NOTE! <==
+@c Determine the edition number in *three* places by hand:
+@c 1. First ifinfo section 2. title page 3. top node
+@c To find the locations, search for !!set
+
+@c GDB CHANGELOG CONSULTED BETWEEN:
+@c Fri Oct 11 23:27:06 1991 John Gilmore (gnu at cygnus.com)
+@c Sat Dec 22 02:51:40 1990 John Gilmore (gnu at cygint)
+
+@c THIS MANUAL REQUIRES TEXINFO-2 macros and info-makers to format properly.
+
+@ifinfo
+@c This is a dir.info fragment to support semi-automated addition of
+@c manuals to an info tree. zoo@cygnus.com is developing this facility.
+@format
+START-INFO-DIR-ENTRY
+* Gdb:: The GNU debugger.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+@c
+@c
+@ifinfo
+This file documents the GNU debugger @value{GDBN}.
+
+@c !!set edition, date, version
+This is Edition 4.09, August 1993,
+of @cite{Debugging with @value{GDBN}: the GNU Source-Level Debugger}
+for GDB Version @value{GDBVN}.
+
+Copyright (C) 1988, '89, '90, '91, '92, '93 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
+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
+
+@titlepage
+@title Debugging with @value{GDBN}
+@subtitle The GNU Source-Level Debugger
+@ifclear GENERIC
+@subtitle (@value{TARGET})
+@end ifclear
+@sp 1
+@c !!set edition, date, version
+@subtitle Edition 4.09, for @value{GDBN} version @value{GDBVN}
+@subtitle August 1993
+@author Richard M. Stallman and Roland H. Pesch
+@page
+@tex
+{\parskip=0pt
+\hfill (Send bugs and comments on @value{GDBN} to bug-gdb\@prep.ai.mit.edu.)\par
+\hfill {\it Debugging with @value{GDBN}}\par
+\hfill \TeX{}info \texinfoversion\par
+\hfill pesch\@cygnus.com\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988, '89, '90, '91, '92, '93 Free Software
+Foundation, Inc.
+@sp 2
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA @*
+Printed copies are available for $20 each. @*
+ISBN 1-882114-11-6 @*
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+@page
+
+@ifinfo
+@node Top
+@top Debugging with @value{GDBN}
+
+This file describes @value{GDBN}, the GNU symbolic debugger.
+
+@c !!set edition, date, version
+This is Edition 4.09, August 1993, for GDB Version @value{GDBVN}.
+
+@menu
+* Summary:: Summary of @value{GDBN}
+@ifset NOVEL
+* New Features:: New features since GDB version 3.5
+@end ifset
+@ifclear BARETARGET
+* Sample Session:: A sample @value{GDBN} session
+@end ifclear
+
+* Invocation:: Getting in and out of @value{GDBN}
+* Commands:: @value{GDBN} commands
+* Running:: Running programs under @value{GDBN}
+* Stopping:: Stopping and continuing
+* Stack:: Examining the stack
+* Source:: Examining source files
+* Data:: Examining data
+@ifclear CONLY
+* Languages:: Using @value{GDBN} with different languages
+@end ifclear
+@ifset CONLY
+* C:: C language support
+@end ifset
+@c remnant makeinfo bug, blank line needed after two end-ifs?
+
+* Symbols:: Examining the symbol table
+* Altering:: Altering execution
+* GDB Files:: @value{GDBN} files
+* Targets:: Specifying a debugging target
+* Controlling GDB:: Controlling @value{GDBN}
+* Sequences:: Canned sequences of commands
+@ifclear DOSHOST
+* Emacs:: Using @value{GDBN} under GNU Emacs
+@end ifclear
+
+* GDB Bugs:: Reporting bugs in @value{GDBN}
+* Command Line Editing:: Facilities of the readline library
+* Using History Interactively::
+@ifset NOVEL
+* Renamed Commands::
+@end ifset
+@ifclear PRECONFIGURED
+* Formatting Documentation:: How to format and print GDB documentation
+* Installing GDB:: Installing GDB
+@end ifclear
+
+* Index:: Index
+@end menu
+@end ifinfo
+
+@node Summary
+@unnumbered Summary of @value{GDBN}
+
+The purpose of a debugger such as @value{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.
+
+@value{GDBN} can do four main kinds of things (plus other things in support of
+these) to help you catch bugs in the act:
+
+@itemize @bullet
+@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 itemize
+
+@ifclear CONLY
+@ifclear MOD2
+You can use @value{GDBN} to debug programs written in C or C++.
+@end ifclear
+@ifset MOD2
+You can use @value{GDBN} to debug programs written in C, C++, and
+Modula-2.
+@end ifset
+@ifset FORTRAN
+@cindex Fortran
+@value{GDBN} can be used to debug programs written in Fortran, although
+it does not yet support entering expressions, printing values, etc.
+using Fortran syntax. It may be necessary to refer to some variables
+with a trailing underscore.
+@end ifset
+@end ifclear
+
+@menu
+* Free Software:: Freely redistributable software
+* Contributors:: Contributors to GDB
+@end menu
+
+@node Free Software
+@unnumberedsec Free software
+
+@value{GDBN} is @dfn{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 cannot take these freedoms away
+from anyone else.
+
+@node Contributors
+@unnumberedsec Contributors to GDB
+
+Richard Stallman was the original author of GDB, and of many other GNU
+programs. Many others have contributed to its development. This
+section attempts to credit major contributors. One of the virtues of
+free software is that everyone is free to contribute to it; with
+regret, we cannot actually acknowledge everyone here. The file
+@file{ChangeLog} in the GDB distribution approximates a blow-by-blow
+account.
+
+Changes much prior to version 2.0 are lost in the mists of time.
+
+@quotation
+@emph{Plea:} Additions to this section are particularly welcome. If you
+or your friends (or enemies, to be evenhanded) have been unfairly
+omitted from this list, we would like to add your names!
+@end quotation
+
+So that they may not regard their long labor as thankless, we
+particularly thank those who shepherded GDB through major releases: Fred
+Fish (releases 4.11, 4.10, 4.9), Stu Grossman and John Gilmore (releases
+4.8, 4.7, 4.6, 4.5, 4.4), John Gilmore (releases 4.3, 4.2, 4.1, 4.0, and
+3.9); Jim Kingdon (releases 3.5, 3.4, 3.3); and Randy Smith (releases
+3.2, 3.1, 3.0). As major maintainer of GDB for some period, each
+contributed significantly to the structure, stability, and capabilities
+of the entire debugger.
+
+Richard Stallman, assisted at various times by Peter TerMaat, Chris
+Hanson, and Richard Mlynarik, handled releases through 2.8.
+
+@ifclear CONLY
+Michael Tiemann is the author of most of the GNU C++ support in GDB,
+with significant additional contributions from Per Bothner. James
+Clark wrote the GNU C++ demangler. Early work on C++ was by Peter
+TerMaat (who also did much general update work leading to release 3.0).
+@end ifclear
+
+GDB 4 uses the BFD subroutine library to examine multiple
+object-file formats; BFD was a joint project of David V.
+Henkel-Wallace, Rich Pixley, Steve Chamberlain, and John Gilmore.
+
+David Johnson wrote the original COFF support; Pace Willison did
+the original support for encapsulated COFF.
+
+Adam de Boor and Bradley Davis contributed the ISI Optimum V support.
+Per Bothner, Noboyuki Hikichi, and Alessandro Forin contributed MIPS
+support. Jean-Daniel Fekete contributed Sun 386i support. Chris
+Hanson improved the HP9000 support. Noboyuki Hikichi and Tomoyuki
+Hasei contributed Sony/News OS 3 support. David Johnson contributed
+Encore Umax support. Jyrki Kuoppala contributed Altos 3068 support.
+Keith Packard contributed NS32K support. Doug Rabson contributed
+Acorn Risc Machine support. Chris Smith contributed Convex support
+(and Fortran debugging). Jonathan Stone contributed Pyramid support.
+Michael Tiemann contributed SPARC support. Tim Tucker contributed
+support for the Gould NP1 and Gould Powernode. Pace Willison
+contributed Intel 386 support. Jay Vosburgh contributed Symmetry
+support.
+
+Rich Schaefer and Peter Schauer helped with support of SunOS shared
+libraries.
+
+Jay Fenlason and Roland McGrath ensured that GDB and GAS agree about
+several machine instruction sets.
+
+Patrick Duval, Ted Goldstein, Vikram Koka and Glenn Engel helped
+develop remote debugging. Intel Corporation and Wind River Systems
+contributed remote debugging modules for their products.
+
+Brian Fox is the author of the readline libraries providing
+command-line editing and command history.
+
+Andrew Beers of SUNY Buffalo wrote the language-switching code,
+@ifset MOD2
+the Modula-2 support,
+@end ifset
+and contributed the Languages chapter of this manual.
+
+Fred Fish wrote most of the support for Unix System Vr4.
+@ifclear CONLY
+He also enhanced the command-completion support to cover C++ overloaded
+symbols.
+@end ifclear
+
+Hitachi America, Ltd. sponsored the support for Hitachi microprocessors.
+
+@ifset NOVEL
+@node New Features
+@unnumbered New Features since GDB Version 3.5
+
+@table @emph
+@item Targets
+Using the new command @code{target}, you can select at runtime whether
+you are debugging local files, local processes, standalone systems over
+a serial port, realtime systems over a TCP/IP connection, etc. The
+command @code{load} can download programs into a remote system. Serial
+stubs are available for Motorola 680x0, Intel 80386, and Sparc remote
+systems; GDB also supports debugging realtime processes running under
+VxWorks, using SunRPC Remote Procedure Calls over TCP/IP to talk to a
+debugger stub on the target system. Internally, GDB now uses a function
+vector to mediate access to different targets; if you need to add your
+own support for a remote protocol, this makes it much easier.
+
+@item Watchpoints
+GDB 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 your program
+where this may happen.
+
+@item Wide Output
+Commands that issue wide output now insert newlines at places designed
+to make the output more readable.
+
+@item Object Code Formats
+GDB uses a new library called the Binary File Descriptor (BFD) Library
+to permit it to switch dynamically, without reconfiguration or
+recompilation, between different object-file formats. Formats currently
+supported are COFF, ELF, a.out, Intel 960 b.out, MIPS ECOFF, HPPA SOM
+(with stabs debugging), and S-records; files may be read as .o files,
+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 and Ports
+Compile-time configuration (to select a particular architecture and
+operating system) is much easier. The script @code{configure} now
+allows you to configure GDB as either a native debugger or a
+cross-debugger. @xref{Installing GDB}, for details on how to
+configure.
+
+@item Interaction
+The user interface to the GDB control variables is simpler,
+and is consolidated in two commands, @code{set} and @code{show}. Output
+lines are now broken at readable places, rather than overflowing onto
+the next line. You can suppress output of machine-level addresses,
+displaying only source language information.
+
+@item C++
+GDB now supports C++ multiple inheritance (if used with a GCC
+version 2 compiler), and also has limited support for C++ exception
+handling, with the commands @code{catch} and @code{info catch}: GDB
+can break when an exception is raised, before the stack is peeled back
+to the exception handler's context.
+
+@ifset MOD2
+@item Modula-2
+GDB now has preliminary support for the GNU Modula-2 compiler, currently
+under development at the State University of New York at Buffalo.
+Coordinated development of both GDB and the GNU Modula-2 compiler will
+continue. Other Modula-2 compilers are currently not supported, and
+attempting to debug programs compiled with them will likely result in an
+error as the symbol table of the executable is read in.
+@end ifset
+
+@item Command Rationalization
+Many GDB commands have been renamed to make them easier to remember
+and use. In particular, the subcommands of @code{info} and
+@code{show}/@code{set} are grouped to make the former refer to the state
+of your program, and the latter refer to the state of GDB itself.
+@xref{Renamed Commands}, for details on what commands were renamed.
+
+@item Shared Libraries
+GDB 4 can debug programs and core files that use SunOS, SVR4, or IBM RS/6000
+shared libraries.
+
+@item Reference Card
+GDB 4 has a reference card. @xref{Formatting Documentation,,Formatting
+the Documentation}, for instructions about how to print it.
+@end table
+@end ifset
+
+@ifclear BARETARGET
+@node Sample Session
+@chapter A Sample @value{GDBN} Session
+
+You can use this manual at your leisure to read all about @value{GDBN}.
+However, a handful of commands are enough to get started using the
+debugger. This chapter illustrates those commands.
+
+@iftex
+In this sample session, we emphasize user input like this: @b{input},
+to make it easier to pick out from the surrounding output.
+@end iftex
+
+@c FIXME: this example may not be appropriate for some configs, where
+@c FIXME...primary interest is in remote use.
+
+One of the preliminary versions of GNU @code{m4} (a generic macro
+processor) exhibits the following bug: sometimes, when we change its
+quote strings from the default, the commands used to capture one macro
+definition within another stop working. In the following short @code{m4}
+session, we define a macro @code{foo} which expands to @code{0000}; we
+then use the @code{m4} built-in @code{defn} to define @code{bar} as the
+same thing. However, when we change the open quote string to
+@code{<QUOTE>} and the close quote string to @code{<UNQUOTE>}, the same
+procedure fails to define a new synonym @code{baz}:
+
+@smallexample
+$ @b{cd gnu/m4}
+$ @b{./m4}
+@b{define(foo,0000)}
+
+@b{foo}
+0000
+@b{define(bar,defn(`foo'))}
+
+@b{bar}
+0000
+@b{changequote(<QUOTE>,<UNQUOTE>)}
+
+@b{define(baz,defn(<QUOTE>foo<UNQUOTE>))}
+@b{baz}
+@b{C-d}
+m4: End of input: 0: fatal error: EOF in string
+@end smallexample
+
+@noindent
+Let us use @value{GDBN} to try to see what is going on.
+
+@smallexample
+$ @b{@value{GDBP} m4}
+@c FIXME: this falsifies the exact text played out, to permit smallbook
+@c FIXME... format to come out better.
+GDB is free software and you are welcome to distribute copies
+ of it under certain conditions; type "show copying" to see
+ the conditions.
+There is absolutely no warranty for GDB; type "show warranty"
+ for details.
+GDB @value{GDBVN}, Copyright 1993 Free Software Foundation, Inc...
+(@value{GDBP})
+@end smallexample
+
+@noindent
+@value{GDBN} reads only enough symbol data to know where to find the rest when
+needed; as a result, the first prompt comes up very quickly. We now
+tell @value{GDBN} to use a narrower display width than usual, so that examples
+will fit in this manual.
+
+@smallexample
+(@value{GDBP}) @b{set width 70}
+@end smallexample
+
+@noindent
+We need to see how the @code{m4} built-in @code{changequote} works.
+Having looked at the source, we know the relevant subroutine is
+@code{m4_changequote}, so we set a breakpoint there with the @value{GDBN}
+@code{break} command.
+
+@smallexample
+(@value{GDBP}) @b{break m4_changequote}
+Breakpoint 1 at 0x62f4: file builtin.c, line 879.
+@end smallexample
+
+@noindent
+Using the @code{run} command, we start @code{m4} running under @value{GDBN}
+control; as long as control does not reach the @code{m4_changequote}
+subroutine, the program runs as usual:
+
+@smallexample
+(@value{GDBP}) @b{run}
+Starting program: /work/Editorial/gdb/gnu/m4/m4
+@b{define(foo,0000)}
+
+@b{foo}
+0000
+@end smallexample
+
+@noindent
+To trigger the breakpoint, we call @code{changequote}. @value{GDBN}
+suspends execution of @code{m4}, displaying information about the
+context where it stops.
+
+@smallexample
+@b{changequote(<QUOTE>,<UNQUOTE>)}
+
+Breakpoint 1, m4_changequote (argc=3, argv=0x33c70)
+ at builtin.c:879
+879 if (bad_argc(TOKEN_DATA_TEXT(argv[0]),argc,1,3))
+@end smallexample
+
+@noindent
+Now we use the command @code{n} (@code{next}) to advance execution to
+the next line of the current function.
+
+@smallexample
+(@value{GDBP}) @b{n}
+882 set_quotes((argc >= 2) ? TOKEN_DATA_TEXT(argv[1])\
+ : nil,
+@end smallexample
+
+@noindent
+@code{set_quotes} looks like a promising subroutine. We can go into it
+by using the command @code{s} (@code{step}) instead of @code{next}.
+@code{step} goes to the next line to be executed in @emph{any}
+subroutine, so it steps into @code{set_quotes}.
+
+@smallexample
+(@value{GDBP}) @b{s}
+set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
+ at input.c:530
+530 if (lquote != def_lquote)
+@end smallexample
+
+@noindent
+The display that shows the subroutine where @code{m4} is now
+suspended (and its arguments) is called a stack frame display. It
+shows a summary of the stack. We can use the @code{backtrace}
+command (which can also be spelled @code{bt}), to see where we are
+in the stack as a whole: the @code{backtrace} command displays a
+stack frame for each active subroutine.
+
+@smallexample
+(@value{GDBP}) @b{bt}
+#0 set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
+ at input.c:530
+#1 0x6344 in m4_changequote (argc=3, argv=0x33c70)
+ at builtin.c:882
+#2 0x8174 in expand_macro (sym=0x33320) at macro.c:242
+#3 0x7a88 in expand_token (obs=0x0, t=209696, td=0xf7fffa30)
+ at macro.c:71
+#4 0x79dc in expand_input () at macro.c:40
+#5 0x2930 in main (argc=0, argv=0xf7fffb20) at m4.c:195
+@end smallexample
+
+@noindent
+We will step through a few more lines to see what happens. The first two
+times, we can use @samp{s}; the next two times we use @code{n} to avoid
+falling into the @code{xstrdup} subroutine.
+
+@smallexample
+(@value{GDBP}) @b{s}
+0x3b5c 532 if (rquote != def_rquote)
+(@value{GDBP}) @b{s}
+0x3b80 535 lquote = (lq == nil || *lq == '\0') ? \
+def_lquote : xstrdup(lq);
+(@value{GDBP}) @b{n}
+536 rquote = (rq == nil || *rq == '\0') ? def_rquote\
+ : xstrdup(rq);
+(@value{GDBP}) @b{n}
+538 len_lquote = strlen(rquote);
+@end smallexample
+
+@noindent
+The last line displayed looks a little odd; we can examine the variables
+@code{lquote} and @code{rquote} to see if they are in fact the new left
+and right quotes we specified. We use the command @code{p}
+(@code{print}) to see their values.
+
+@smallexample
+(@value{GDBP}) @b{p lquote}
+$1 = 0x35d40 "<QUOTE>"
+(@value{GDBP}) @b{p rquote}
+$2 = 0x35d50 "<UNQUOTE>"
+@end smallexample
+
+@noindent
+@code{lquote} and @code{rquote} are indeed the new left and right quotes.
+To look at some context, we can display ten lines of source
+surrounding the current line with the @code{l} (@code{list}) command.
+
+@smallexample
+(@value{GDBP}) @b{l}
+533 xfree(rquote);
+534
+535 lquote = (lq == nil || *lq == '\0') ? def_lquote\
+ : xstrdup (lq);
+536 rquote = (rq == nil || *rq == '\0') ? def_rquote\
+ : xstrdup (rq);
+537
+538 len_lquote = strlen(rquote);
+539 len_rquote = strlen(lquote);
+540 @}
+541
+542 void
+@end smallexample
+
+@noindent
+Let us step past the two lines that set @code{len_lquote} and
+@code{len_rquote}, and then examine the values of those variables.
+
+@smallexample
+(@value{GDBP}) @b{n}
+539 len_rquote = strlen(lquote);
+(@value{GDBP}) @b{n}
+540 @}
+(@value{GDBP}) @b{p len_lquote}
+$3 = 9
+(@value{GDBP}) @b{p len_rquote}
+$4 = 7
+@end smallexample
+
+@noindent
+That certainly looks wrong, assuming @code{len_lquote} and
+@code{len_rquote} are meant to be the lengths of @code{lquote} and
+@code{rquote} respectively. We can set them to better values using
+the @code{p} command, since it can print the value of
+any expression---and that expression can include subroutine calls and
+assignments.
+
+@smallexample
+(@value{GDBP}) @b{p len_lquote=strlen(lquote)}
+$5 = 7
+(@value{GDBP}) @b{p len_rquote=strlen(rquote)}
+$6 = 9
+@end smallexample
+
+@noindent
+Is that enough to fix the problem of using the new quotes with the
+@code{m4} built-in @code{defn}? We can allow @code{m4} to continue
+executing with the @code{c} (@code{continue}) command, and then try the
+example that caused trouble initially:
+
+@smallexample
+(@value{GDBP}) @b{c}
+Continuing.
+
+@b{define(baz,defn(<QUOTE>foo<UNQUOTE>))}
+
+baz
+0000
+@end smallexample
+
+@noindent
+Success! The new quotes now work just as well as the default ones. The
+problem seems to have been just the two typos defining the wrong
+lengths. We allow @code{m4} exit by giving it an EOF as input:
+
+@smallexample
+@b{C-d}
+Program exited normally.
+@end smallexample
+
+@noindent
+The message @samp{Program exited normally.} is from @value{GDBN}; it
+indicates @code{m4} has finished executing. We can end our @value{GDBN}
+session with the @value{GDBN} @code{quit} command.
+
+@smallexample
+(@value{GDBP}) @b{quit}
+@end smallexample
+@end ifclear
+
+@node Invocation
+@chapter Getting In and Out of @value{GDBN}
+
+This chapter discusses how to start @value{GDBN}, and how to get out of it.
+(The essentials: type @samp{@value{GDBP}} to start GDB, and type @kbd{quit}
+or @kbd{C-d} to exit.)
+
+@menu
+* Invoking GDB:: How to start @value{GDBN}
+* Quitting GDB:: How to quit @value{GDBN}
+* Shell Commands:: How to use shell commands inside @value{GDBN}
+@end menu
+
+@node Invoking GDB
+@section Invoking @value{GDBN}
+
+@ifset H8EXCLUSIVE
+For details on starting up @value{GDBP} as a
+remote debugger attached to a Hitachi microprocessor, see @ref{Hitachi
+Remote,,@value{GDBN} and Hitachi Microprocessors}.
+@end ifset
+
+Invoke @value{GDBN} by running the program @code{@value{GDBP}}. Once started,
+@value{GDBN} reads commands from the terminal until you tell it to exit.
+
+You can also run @code{@value{GDBP}} with a variety of arguments and options,
+to specify more of your debugging environment at the outset.
+
+@ifset GENERIC
+The command-line options described here are designed
+to cover a variety of situations; in some environments, some of these
+options may effectively be unavailable.
+@end ifset
+
+The most usual way to start @value{GDBN} is with one argument,
+specifying an executable program:
+
+@example
+@value{GDBP} @var{program}
+@end example
+
+@ifclear BARETARGET
+@noindent
+You can also start with both an executable program and a core file
+specified:
+
+@example
+@value{GDBP} @var{program} @var{core}
+@end example
+
+You can, instead, specify a process ID as a second argument, if you want
+to debug a running process:
+
+@example
+@value{GDBP} @var{program} 1234
+@end example
+
+@noindent
+would attach @value{GDBN} to process @code{1234} (unless you also have a file
+named @file{1234}; @value{GDBN} does check for a core file first).
+
+Taking advantage of the second command-line argument requires a fairly
+complete operating system; when you use @value{GDBN} as a remote debugger
+attached to a bare board, there may not be any notion of ``process'',
+and there is often no way to get a core dump.
+@end ifclear
+
+@noindent
+You can further control how @value{GDBN} starts up by using command-line
+options. @value{GDBN} itself can remind you of the options available.
+
+@noindent
+Type
+
+@example
+@value{GDBP} -help
+@end example
+
+@noindent
+to display all available options and briefly describe their use
+(@samp{@value{GDBP} -h} is a shorter equivalent).
+
+All options and command line arguments you give are processed
+in sequential order. The order makes a difference when the
+@samp{-x} option is used.
+
+
+@menu
+@ifclear GENERIC
+@ifset REMOTESTUB
+* Remote Serial:: @value{GDBN} remote serial protocol
+@end ifset
+@ifset I960
+* i960-Nindy Remote:: @value{GDBN} with a remote i960 (Nindy)
+@end ifset
+@ifset AMD29K
+* UDI29K Remote:: @value{GDBN} and the UDI protocol for AMD29K
+* EB29K Remote:: @value{GDBN} with a remote EB29K
+@end ifset
+@ifset VXWORKS
+* VxWorks Remote:: @value{GDBN} and VxWorks
+@end ifset
+@ifset ST2000
+* ST2000 Remote:: @value{GDBN} with a Tandem ST2000
+@end ifset
+@ifset H8
+* Hitachi Remote:: @value{GDBN} and Hitachi Microprocessors
+@end ifset
+@ifset MIPS
+* MIPS Remote:: @value{GDBN} and MIPS boards
+@end ifset
+@ifset SIMS
+* Simulator:: Simulated CPU target
+@end ifset
+@end ifclear
+@c remnant makeinfo bug requires this blank line after *two* end-ifblahs:
+
+* File Options:: Choosing files
+* Mode Options:: Choosing modes
+@end menu
+
+@ifclear GENERIC
+@include remote.texi
+@end ifclear
+
+@node File Options
+@subsection Choosing files
+
+@ifclear BARETARGET
+When @value{GDBN} starts, it reads any arguments other than options as
+specifying an executable file and core file (or process ID). This is
+the same as if the arguments were specified by the @samp{-se} and
+@samp{-c} options respectively. (@value{GDBN} reads the first argument
+that does not have an associated option flag as equivalent to the
+@samp{-se} option followed by that argument; and the second argument
+that does not have an associated option flag, if any, as equivalent to
+the @samp{-c} option followed by that argument.)
+@end ifclear
+@ifset BARETARGET
+When @value{GDBN} starts, it reads any argument other than options as
+specifying an executable file. This is the same as if the argument was
+specified by the @samp{-se} option.
+@end ifset
+
+Many options have both long and short forms; both are shown in the
+following list. @value{GDBN} also recognizes the long forms if you truncate
+them, so long as enough of the option is present to be unambiguous.
+(If you prefer, you can flag option arguments with @samp{--} rather
+than @samp{-}, though we illustrate the more usual convention.)
+
+@table @code
+@item -symbols @var{file}
+@itemx -s @var{file}
+Read symbol table from file @var{file}.
+
+@item -exec @var{file}
+@itemx -e @var{file}
+Use file @var{file} as the executable file to execute when
+@ifset BARETARGET
+appropriate.
+@end ifset
+@ifclear BARETARGET
+appropriate, and for examining pure data in conjunction with a core
+dump.
+@end ifclear
+
+@item -se @var{file}
+Read symbol table from file @var{file} and use it as the executable
+file.
+
+@ifclear BARETARGET
+@item -core @var{file}
+@itemx -c @var{file}
+Use file @var{file} as a core dump to examine.
+
+@item -c @var{number}
+Connect to process ID @var{number}, as with the @code{attach} command
+(unless there is a file in core-dump format named @var{number}, in which
+case @samp{-c} specifies that file as a core dump to read).
+@end ifclear
+
+@item -command @var{file}
+@itemx -x @var{file}
+Execute @value{GDBN} commands from file @var{file}. @xref{Command
+Files,, Command files}.
+
+@item -directory @var{directory}
+@itemx -d @var{directory}
+Add @var{directory} to the path to search for source files.
+
+@ifclear BARETARGET
+@item -m
+@itemx -mapped
+@emph{Warning: this option depends on operating system facilities that are not
+supported on all systems.}@*
+If memory-mapped files are available on your system through the @code{mmap}
+system call, you can use this option
+to have @value{GDBN} write the symbols from your
+program into a reusable file in the current directory. If the program you are debugging is
+called @file{/tmp/fred}, the mapped symbol file will be @file{./fred.syms}.
+Future @value{GDBN} debugging sessions will notice the presence of this file,
+and will quickly map in symbol information from it, rather than reading
+the symbol table from the executable program.
+
+@c FIXME! Really host, not target?
+The @file{.syms} file is specific to the host machine where @value{GDBN}
+is run. It holds an exact image of the internal @value{GDBN} symbol
+table. It cannot be shared across multiple host platforms.
+@end ifclear
+
+@item -r
+@itemx -readnow
+Read each symbol file's entire symbol table immediately, rather than
+the default, which is to read it incrementally as it is needed.
+This makes startup slower, but makes future operations faster.
+@end table
+
+@ifclear BARETARGET
+The @code{-mapped} and @code{-readnow} options are typically combined in
+order to build a @file{.syms} file that contains complete symbol
+information. (@xref{Files,,Commands to specify files}, for information
+on @file{.syms} files.) A simple GDB invocation to do nothing but build
+a @file{.syms} file for future use is:
+
+@example
+ gdb -batch -nx -mapped -readnow programname
+@end example
+@end ifclear
+
+@node Mode Options
+@subsection Choosing modes
+
+You can run @value{GDBN} in various alternative modes---for example, in
+batch mode or quiet mode.
+
+@table @code
+@item -nx
+@itemx -n
+Do not execute commands from any initialization files (normally called
+@file{@value{GDBINIT}}). Normally, the commands in these files are
+executed after all the command options and arguments have been
+processed. @xref{Command Files,,Command files}.
+
+@item -quiet
+@itemx -q
+``Quiet''. Do not print the introductory and copyright messages. These
+messages are also suppressed in batch mode.
+
+@item -batch
+Run in batch mode. Exit with status @code{0} after processing all the
+command files specified with @samp{-x} (and all commands from
+initialization files, if not inhibited with @samp{-n}). Exit with
+nonzero status if an error occurs in executing the @value{GDBN} commands
+in the command files.
+
+Batch mode may be useful for running @value{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 @value{GDBN} control
+terminates) is not issued when running in batch mode.
+
+@item -cd @var{directory}
+Run @value{GDBN} using @var{directory} as its working directory,
+instead of the current directory.
+
+@ifset LUCID
+@item -context @var{authentication}
+When the Energize programming system starts up @value{GDBN}, it uses this
+option to trigger an alternate mode of interaction.
+@var{authentication} is a pair of numeric codes that identify @value{GDBN}
+as a client in the Energize environment. Avoid this option when you run
+@value{GDBN} directly from the command line. See @ref{Energize,,Using
+@value{GDBN} with Energize} for more discussion of using @value{GDBN} with Energize.
+@end ifset
+
+@ifclear DOSHOST
+@item -fullname
+@itemx -f
+Emacs sets this option when it runs @value{GDBN} as a subprocess. It tells @value{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 your 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-@value{GDBN} interface program uses the two @samp{\032} characters as
+a signal to display the source code for the frame.
+@end ifclear
+
+@ifset SERIAL
+@item -b @var{bps}
+Set the line speed (baud rate or bits per second) of any serial
+interface used by @value{GDBN} for remote debugging.
+
+@item -tty @var{device}
+Run using @var{device} for your program's standard input and output.
+@c FIXME: kingdon thinks there is more to -tty. Investigate.
+@end ifset
+@end table
+
+@node Quitting GDB
+@section Quitting @value{GDBN}
+@cindex exiting @value{GDBN}
+@cindex leaving @value{GDBN}
+
+@table @code
+@item quit
+@kindex quit
+@kindex q
+To exit @value{GDBN}, use the @code{quit} command (abbreviated @code{q}), or type
+an end-of-file character (usually @kbd{C-d}).
+@end table
+
+@cindex interrupt
+An interrupt (often @kbd{C-c}) will not exit from @value{GDBN}, but rather
+will terminate the action of any @value{GDBN} command that is in progress and
+return to @value{GDBN} command level. It is safe to type the interrupt
+character at any time because @value{GDBN} does not allow it to take effect
+until a time when it is safe.
+
+@ifclear BARETARGET
+If you have been using @value{GDBN} to control an attached process or
+device, you can release it with the @code{detach} command
+(@pxref{Attach, ,Debugging an already-running process}).
+@end ifclear
+
+@node Shell Commands
+@section Shell commands
+
+If you need to execute occasional shell commands during your
+debugging session, there is no need to leave or suspend @value{GDBN}; you can
+just use the @code{shell} command.
+
+@table @code
+@item shell @var{command string}
+@kindex shell
+@cindex shell escape
+Invoke a the standard shell to execute @var{command string}.
+@ifclear DOSHOST
+If it exists, the environment variable @code{SHELL} determines which
+shell to run. Otherwise @value{GDBN} uses @code{/bin/sh}.
+@end ifclear
+@end table
+
+The utility @code{make} is often needed in development environments.
+You do not have to use the @code{shell} command for this purpose in
+@value{GDBN}:
+
+@table @code
+@item make @var{make-args}
+@kindex make
+@cindex calling make
+Execute the @code{make} program with the specified
+arguments. This is equivalent to @samp{shell make @var{make-args}}.
+@end table
+
+@node Commands
+@chapter @value{GDBN} Commands
+
+You can abbreviate a @value{GDBN} command to the first few letters of the command
+name, if that abbreviation is unambiguous; and you can repeat certain
+@value{GDBN} commands by typing just @key{RET}. You can also use the @key{TAB}
+key to get @value{GDBN} to fill out the rest of a word in a command (or to
+show you the alternatives available, if there is more than one possibility).
+
+@menu
+* Command Syntax:: How to give commands to @value{GDBN}
+* Completion:: Command completion
+* Help:: How to ask @value{GDBN} for help
+@end menu
+
+@node Command Syntax
+@section Command syntax
+
+A @value{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 @code{step} accepts an argument which is the number of times to
+step, as in @samp{step 5}. You can also use the @code{step} command
+with no arguments. Some command names do not allow any arguments.
+
+@cindex abbreviation
+@value{GDBN} command names may always be truncated if that abbreviation is
+unambiguous. Other possible command abbreviations are listed in the
+documentation for individual commands. In some cases, even ambiguous
+abbreviations are allowed; for example, @code{s} is specially defined as
+equivalent to @code{step} even though there are other commands whose
+names start with @code{s}. You can test abbreviations by using them as
+arguments to the @code{help} command.
+
+@cindex repeating commands
+@kindex RET
+A blank line as input to @value{GDBN} (typing just @key{RET}) means to
+repeat the previous command. Certain commands (for example, @code{run})
+will not repeat this way; these are commands for which unintentional
+repetition might cause trouble and which you are unlikely to want to
+repeat.
+
+The @code{list} and @code{x} commands, when you repeat them with
+@key{RET}, construct new arguments rather than repeating
+exactly as typed. This permits easy scanning of source or memory.
+
+@value{GDBN} can also use @key{RET} in another way: to partition lengthy
+output, in a way similar to the common utility @code{more}
+(@pxref{Screen Size,,Screen size}). Since it is easy to press one
+@key{RET} too many in this situation, @value{GDBN} disables command
+repetition after any command that generates this sort of display.
+
+@kindex #
+@cindex comment
+Any text from a @kbd{#} to the end of the line is a comment; it does
+nothing. This is useful mainly in command files (@pxref{Command
+Files,,Command files}).
+
+@node Completion
+@section Command completion
+
+@cindex completion
+@cindex word completion
+@value{GDBN} can fill in the rest of a word in a command for you, if there is
+only one possibility; it can also show you what the valid possibilities
+are for the next word in a command, at any time. This works for @value{GDBN}
+commands, @value{GDBN} subcommands, and the names of symbols in your program.
+
+Press the @key{TAB} key whenever you want @value{GDBN} to fill out the rest
+of a word. If there is only one possibility, @value{GDBN} will fill in the
+word, and wait for you to finish the command (or press @key{RET} to
+enter it). For example, if you type
+
+@c FIXME "@key" does not distinguish its argument sufficiently to permit
+@c complete accuracy in these examples; space introduced for clarity.
+@c If texinfo enhancements make it unnecessary, it would be nice to
+@c replace " @key" by "@key" in the following...
+@example
+(@value{GDBP}) info bre @key{TAB}
+@end example
+
+@noindent
+@value{GDBN} fills in the rest of the word @samp{breakpoints}, since that is
+the only @code{info} subcommand beginning with @samp{bre}:
+
+@example
+(@value{GDBP}) info breakpoints
+@end example
+
+@noindent
+You can either press @key{RET} at this point, to run the @code{info
+breakpoints} command, or backspace and enter something else, if
+@samp{breakpoints} does not look like the command you expected. (If you
+were sure you wanted @code{info breakpoints} in the first place, you
+might as well just type @key{RET} immediately after @samp{info bre},
+to exploit command abbreviations rather than command completion).
+
+If there is more than one possibility for the next word when you press
+@key{TAB}, @value{GDBN} will sound a bell. You can either supply more
+characters and try again, or just press @key{TAB} a second time, and
+@value{GDBN} will display all the possible completions for that word. For
+example, you might want to set a breakpoint on a subroutine whose name
+begins with @samp{make_}, but when you type @kbd{b make_@key{TAB}} @value{GDBN}
+just sounds the bell. Typing @key{TAB} again will display all the
+function names in your program that begin with those characters, for
+example:
+
+@example
+(@value{GDBP}) b make_ @key{TAB}
+@exdent @value{GDBN} sounds bell; press @key{TAB} again, to see:
+make_a_section_from_file make_environ
+make_abs_section make_function_type
+make_blockvector make_pointer_type
+make_cleanup make_reference_type
+make_command make_symbol_completion_list
+(@value{GDBP}) b make_
+@end example
+
+@noindent
+After displaying the available possibilities, @value{GDBN} copies your
+partial input (@samp{b make_} in the example) so you can finish the
+command.
+
+If you just want to see the list of alternatives in the first place, you
+can press @kbd{M-?} rather than pressing @key{TAB} twice. @kbd{M-?}
+means @kbd{@key{META} ?}. You can type this
+@ifclear DOSHOST
+either by holding down a
+key designated as the @key{META} shift on your keyboard (if there is
+one) while typing @kbd{?}, or
+@end ifclear
+as @key{ESC} followed by @kbd{?}.
+
+@cindex quotes in commands
+@cindex completion of quoted strings
+Sometimes the string you need, while logically a ``word'', may contain
+parentheses or other characters that @value{GDBN} normally excludes from its
+notion of a word. To permit word completion to work in this situation,
+you may enclose words in @code{'} (single quote marks) in @value{GDBN} commands.
+
+@ifclear CONLY
+The most likely situation where you might need this is in typing the
+name of a C++ function. This is because C++ allows function overloading
+(multiple definitions of the same function, distinguished by argument
+type). For example, when you want to set a breakpoint you may need to
+distinguish whether you mean the version of @code{name} that takes an
+@code{int} parameter, @code{name(int)}, or the version that takes a
+@code{float} parameter, @code{name(float)}. To use the word-completion
+facilities in this situation, type a single quote @code{'} at the
+beginning of the function name. This alerts @value{GDBN} that it may need to
+consider more information than usual when you press @key{TAB} or
+@kbd{M-?} to request word completion:
+
+@example
+(@value{GDBP}) b 'bubble( @key{M-?}
+bubble(double,double) bubble(int,int)
+(@value{GDBP}) b 'bubble(
+@end example
+
+In some cases, @value{GDBN} can tell that completing a name will require
+quotes. When this happens, @value{GDBN} will insert the quote for you (while
+completing as much as it can) if you do not type the quote in the first
+place:
+
+@example
+(@value{GDBP}) b bub @key{TAB}
+@exdent @value{GDBN} alters your input line to the following, and rings a bell:
+(@value{GDBP}) b 'bubble(
+@end example
+
+@noindent
+In general, @value{GDBN} can tell that a quote is needed (and inserts it) if
+you have not yet started typing the argument list when you ask for
+completion on an overloaded symbol.
+@end ifclear
+
+
+@node Help
+@section Getting help
+@cindex online documentation
+@kindex help
+
+You can always ask @value{GDBN} itself for information on its commands, using the
+command @code{help}.
+
+@table @code
+@item help
+@itemx h
+@kindex h
+You can use @code{help} (abbreviated @code{h}) with no arguments to
+display a short list of named classes of commands:
+
+@smallexample
+(@value{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.
+(@value{GDBP})
+@end smallexample
+
+@item help @var{class}
+Using one of the general help classes as an argument, you can get a
+list of the individual commands in that class. For example, here is the
+help display for the class @code{status}:
+
+@smallexample
+(@value{GDBP}) help status
+Status inquiries.
+
+List of commands:
+
+@c Line break in "show" line falsifies real output, but needed
+@c to fit in smallbook page size.
+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.
+(@value{GDBP})
+@end smallexample
+
+@item help @var{command}
+With a command name as @code{help} argument, @value{GDBN} will display a
+short paragraph on how to use that command.
+@end table
+
+In addition to @code{help}, you can use the @value{GDBN} commands @code{info}
+and @code{show} to inquire about the state of your program, or the state
+of @value{GDBN} itself. Each command supports many 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. @xref{Index}.
+
+@c @group
+@table @code
+@item info
+@kindex info
+@kindex i
+This command (abbreviated @code{i}) is for describing the state of your
+program. For example, you can list the arguments given to your program
+with @code{info args}, list the registers currently in use with @code{info
+registers}, or list the breakpoints you have set with @code{info breakpoints}.
+You can get a complete list of the @code{info} sub-commands with
+@w{@code{help info}}.
+
+@kindex show
+@item show
+In contrast, @code{show} is for describing the state of @value{GDBN} itself.
+You can change most of the things you can @code{show}, by using the
+related command @code{set}; for example, you can control what number
+system is used for displays with @code{set radix}, or simply inquire
+which is currently in use with @code{show radix}.
+
+@kindex info set
+To display all the settable parameters and their current
+values, you can use @code{show} with no arguments; you may also use
+@code{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"?
+@end table
+@c @end group
+
+Here are three miscellaneous @code{show} subcommands, all of which are
+exceptional in lacking corresponding @code{set} commands:
+
+@table @code
+@kindex show version
+@cindex version number
+@item show version
+Show what version of @value{GDBN} is running. You should include this
+information in @value{GDBN} bug-reports. If multiple versions of @value{GDBN} are in
+use at your site, you may occasionally want to determine which version
+of @value{GDBN} you are running; as @value{GDBN} evolves, new commands are introduced,
+and old ones may wither away. The version number is also announced
+when you start @value{GDBN}.
+
+@kindex show copying
+@item show copying
+Display information about permission for copying @value{GDBN}.
+
+@kindex show warranty
+@item show warranty
+Display the GNU ``NO WARRANTY'' statement.
+@end table
+
+@node Running
+@chapter Running Programs Under @value{GDBN}
+
+When you run a program under @value{GDBN}, you must first generate
+debugging information when you compile it.
+@ifclear BARETARGET
+You may start it with its arguments, if any, in an environment of your
+choice. You may redirect your program's input and output, debug an
+already running process, or kill a child process.
+@end ifclear
+
+@menu
+* Compilation:: Compiling for debugging
+* Starting:: Starting your program
+@ifclear BARETARGET
+* Arguments:: Your program's arguments
+* Environment:: Your program's environment
+* Working Directory:: Your program's working directory
+* Input/Output:: Your program's input and output
+* Attach:: Debugging an already-running process
+* Kill Process:: Killing the child process
+* Process Information:: Additional process information
+@end ifclear
+@end menu
+
+@node Compilation
+@section Compiling for debugging
+
+In order to debug a program effectively, you need to generate
+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.
+
+Many C compilers are unable to handle the @samp{-g} and @samp{-O}
+options together. Using those compilers, you cannot generate optimized
+executables containing debugging information.
+
+@value{NGCC}, 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 your program is correct, but there is no sense in pushing
+your luck.
+
+@cindex optimized code, debugging
+@cindex debugging optimized code
+When you debug a program compiled with @samp{-g -O}, remember that the
+optimizer is rearranging your code; the debugger will show you what is
+really there. Do not be too surprised when the execution path does not
+exactly match your source file! An extreme example: if you define a
+variable, but never use it, @value{GDBN} will never see that
+variable---because the compiler optimizes it out of existence.
+
+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!).
+
+Older versions of the GNU C compiler permitted a variant option
+@w{@samp{-gg}} for debugging information. @value{GDBN} no longer supports this
+format; if your GNU C compiler has this option, do not use it.
+
+@need 2000
+@node Starting
+@section Starting your program
+@cindex starting
+@cindex running
+
+@table @code
+@item run
+@itemx r
+@kindex run
+Use the @code{run} command to start your program under @value{GDBN}. You must
+first specify the program name
+@ifset VXWORKS
+(except on VxWorks)
+@end ifset
+with an argument to @value{GDBN} (@pxref{Invocation, ,Getting In and
+Out of @value{GDBN}}), or by using the @code{file} or @code{exec-file}
+command (@pxref{Files, ,Commands to specify files}).
+
+@end table
+
+@ifclear BARETARGET
+If you are running your program in an execution environment that
+supports processes, @code{run} creates an inferior process and makes
+that process run your program. (In environments without processes,
+@code{run} jumps to the start of your program.)
+
+The execution of a program is affected by certain information it
+receives from its superior. @value{GDBN} provides ways to specify this
+information, which you must do @emph{before} starting your program. (You
+can change it after starting your program, but such changes will only affect
+your program the next time you start it.) This information may be
+divided into four categories:
+
+@table @asis
+@item The @emph{arguments.}
+Specify the arguments to give your program as the arguments of the
+@code{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
+(such as wildcard expansion or variable substitution) in describing
+the arguments. In Unix systems, you can control which shell is used
+with the @code{SHELL} environment variable. @xref{Arguments, ,Your
+program's arguments}.
+
+@item The @emph{environment.}
+Your program normally inherits its environment from @value{GDBN}, but you can
+use the @value{GDBN} commands @code{set environment} and @code{unset
+environment} to change parts of the environment that will be given to
+your program. @xref{Environment, ,Your program's environment}.
+
+@item The @emph{working directory.}
+Your program inherits its working directory from @value{GDBN}. You can set
+the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+@xref{Working Directory, ,Your program's working directory}.
+
+@item The @emph{standard input and output.}
+Your program normally uses the same device for standard input and
+standard output as @value{GDBN} is using. You can redirect input and output
+in the @code{run} command line, or you can use the @code{tty} command to
+set a different device for your program.
+@xref{Input/Output, ,Your program's input and output}.
+
+@cindex pipes
+@emph{Warning:} While input and output redirection work, you cannot use
+pipes to pass the output of the program you are debugging to another
+program; if you attempt this, @value{GDBN} is likely to wind up debugging the
+wrong program.
+@end table
+@end ifclear
+
+When you issue the @code{run} command, your program begins to execute
+immediately. @xref{Stopping, ,Stopping and continuing}, for discussion
+of how to arrange for your program to stop. Once your program has
+stopped, you may call functions in your program, using the @code{print}
+or @code{call} commands. @xref{Data, ,Examining Data}.
+
+If the modification time of your symbol file has changed since the
+last time @value{GDBN} read its symbols, @value{GDBN} will discard its symbol table and
+re-read it. When it does this, @value{GDBN} tries to retain your current
+breakpoints.
+
+@ifclear BARETARGET
+@node Arguments
+@section Your program's arguments
+
+@cindex arguments (to your program)
+The arguments to your program can be specified by the arguments of the
+@code{run} command. They are passed to a shell, which expands wildcard
+characters and performs redirection of I/O, and thence to your program.
+Your @code{SHELL} environment variable (if it exists) specifies what
+shell @value{GDBN} if you do not define @code{SHELL}, @value{GDBN} uses
+@code{/bin/sh}.
+
+@code{run} with no arguments uses the same arguments used by the previous
+@code{run}, or those set by the @code{set args} command.
+
+@kindex set args
+@table @code
+@item set args
+Specify the arguments to be used the next time your program is run. If
+@code{set args} has no arguments, @code{run} will execute your program
+with no arguments. Once you have run your program with arguments,
+using @code{set args} before the next @code{run} is the only way to run
+it again without arguments.
+
+@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 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 your program with a modified
+environment without having to start @value{GDBN} over again.
+
+@table @code
+@item path @var{directory}
+@kindex path
+Add @var{directory} to the front of the @code{PATH} environment variable
+(the search path for executables), for both @value{GDBN} and your program.
+You may specify several directory names, separated by @samp{:} or
+whitespace. If @var{directory} is already in the path, it is moved to
+the front, so it will be searched sooner.
+
+You can use the string @samp{$cwd} to refer to whatever is the current
+working directory at the time @value{GDBN} searches the path. If you
+use @samp{.} instead, it refers to the directory where you executed the
+@code{path} command. @value{GDBN} replaces @samp{.} in the
+@var{directory} argument (with the current path) before adding
+@var{directory} to the search path.
+@c 'path' is explicitly nonrepeatable, but RMS points out it is silly to
+@c document that, since repeating it would be a no-op.
+
+@item show paths
+@kindex show paths
+Display the list of search paths for executables (the @code{PATH}
+environment variable).
+
+@item show environment @r{[}@var{varname}@r{]}
+@kindex show environment
+Print the value of environment variable @var{varname} to be given to
+your program when it starts. If you do not supply @var{varname},
+print the names and values of all environment variables to be given to
+your program. You can abbreviate @code{environment} as @code{env}.
+
+@item set environment @var{varname} @r{[}=@r{]} @var{value}
+@kindex set environment
+Set environment variable @var{varname} to @var{value}. The value
+changes for your program only, not for @value{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.
+@c "any string" here does not include leading, trailing
+@c blanks. Gnu asks: does anyone care?
+
+For example, this command:
+
+@example
+set env USER = foo
+@end example
+
+@noindent
+tells a Unix program, when subsequently run, that its user is named
+@samp{foo}. (The spaces around @samp{=} are used for clarity here; they
+are not actually required.)
+
+@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} =};
+@code{unset environment} removes the variable from the environment,
+rather than assigning it an empty value.
+@end table
+
+@emph{Warning:} @value{GDBN} runs your program using the shell indicated
+by your @code{SHELL} environment variable if it exists (or
+@code{/bin/sh} if not). If your @code{SHELL} variable names a shell
+that runs an initialization file---such as @file{.cshrc} for C-shell, or
+@file{.bashrc} for BASH---any variables you set in that file will affect
+your program. You may wish to move setting of environment variables to
+files that are only run when you sign on, such as @file{.login} or
+@file{.profile}.
+
+@node Working Directory
+@section Your program's working directory
+
+@cindex working directory (of your program)
+Each time you start your program with @code{run}, it inherits its
+working directory from the current working directory of @value{GDBN}.
+The @value{GDBN} working directory is initially whatever it inherited
+from its parent process (typically the shell), but you can specify a new
+working directory in @value{GDBN} with the @code{cd} command.
+
+The @value{GDBN} working directory also serves as a default for the commands
+that specify files for @value{GDBN} to operate on. @xref{Files, ,Commands to
+specify files}.
+
+@table @code
+@item cd @var{directory}
+@kindex cd
+Set the @value{GDBN} working directory to @var{directory}.
+
+@item pwd
+@kindex pwd
+Print the @value{GDBN} working directory.
+@end table
+
+@node Input/Output
+@section Your program's input and output
+
+@cindex redirection
+@cindex i/o
+@cindex terminal
+By default, the program you run under @value{GDBN} does input and output to
+the same terminal that @value{GDBN} uses. @value{GDBN} switches the terminal to
+its own terminal modes to interact with you, but it records the terminal
+modes your program was using and switches back to them when you continue
+running your program.
+
+@table @code
+@item info terminal
+@kindex info terminal
+Displays information recorded by @value{GDBN} about the terminal modes your
+program is using.
+@end table
+
+You can redirect your program's input and/or output using shell
+redirection with the @code{run} command. For example,
+
+@example
+run > outfile
+@end example
+
+@noindent
+starts your program, diverting its output to the file @file{outfile}.
+
+@kindex tty
+@cindex controlling terminal
+Another way to specify where your program should do input and output is
+with the @code{tty} command. This command accepts a file name as
+argument, and causes this file to be the default for future @code{run}
+commands. It also resets the controlling terminal for the child
+process, for future @code{run} commands. For example,
+
+@example
+tty /dev/ttyb
+@end example
+
+@noindent
+directs that processes started with subsequent @code{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 @code{run} overrides the @code{tty} command's
+effect on the input/output device, but not its effect on the controlling
+terminal.
+
+When you use the @code{tty} command or redirect input in the @code{run}
+command, only the input @emph{for your program} is affected. The input
+for @value{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---one that was started
+outside @value{GDBN}. (@code{info files} will show your active
+targets.) The command takes as argument a process ID. The usual way to
+find out the process-id of a Unix process is with the @code{ps} utility,
+or with the @samp{jobs -l} shell command.
+
+@code{attach} will not repeat if you press @key{RET} a second time after
+executing the command.
+@end table
+
+To use @code{attach}, your program must be running in an environment
+which supports processes; for example, @code{attach} does not work for
+programs on bare-board targets that lack an operating system. You must
+also have permission to send the process a signal.
+
+When using @code{attach}, you should first use the @code{file} command
+to specify the program running in the process and load its symbol table.
+@xref{Files, ,Commands to Specify Files}.
+
+The first thing @value{GDBN} does after arranging to debug the specified
+process is to stop it. You can examine and modify an attached process
+with all the @value{GDBN} commands that are ordinarily available when you start
+processes with @code{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 @code{continue} command after
+attaching @value{GDBN} to the process.
+
+@table @code
+@item detach
+@kindex detach
+When you have finished debugging the attached process, you can use the
+@code{detach} command to release it from @value{GDBN} control. Detaching
+the process continues its execution. After the @code{detach} command,
+that process and @value{GDBN} become completely independent once more, and you
+are ready to @code{attach} another process or start one with @code{run}.
+@code{detach} will not repeat if you press @key{RET} again after
+executing the command.
+@end table
+
+If you exit @value{GDBN} or use the @code{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 you need to confirm by using the @code{set confirm} command
+(@pxref{Messages/Warnings, ,Optional warnings and messages}).
+
+@node Kill Process
+@c @group
+@section Killing the child process
+
+@table @code
+@item kill
+@kindex kill
+Kill the child process in which your program is running under @value{GDBN}.
+@end table
+
+This command is useful if you wish to debug a core dump instead of a
+running process. @value{GDBN} ignores any core dump file while your program
+is running.
+@c @end group
+
+On some operating systems, a program cannot be executed outside @value{GDBN}
+while you have breakpoints set on it inside @value{GDBN}. You can use the
+@code{kill} command in this situation to permit running your program
+outside the debugger.
+
+The @code{kill} command is also useful if you wish to recompile and
+relink your program, since on many systems it is impossible to modify an
+executable file while it is running in a process. In this case, when you
+next type @code{run}, @value{GDBN} will notice that the file has changed, and
+will re-read the symbol table (while trying to preserve your current
+breakpoint settings).
+
+@node Process Information
+@section Additional process information
+
+@kindex /proc
+@cindex process image
+Some operating systems provide a facility called @samp{/proc} that can
+be used to examine the image of a running process using file-system
+subroutines. If @value{GDBN} is configured for an operating system with this
+facility, the command @code{info proc} is available to report on several
+kinds of information about the process running your program.
+
+@table @code
+@item info proc
+@kindex info proc
+Summarize available information about the process.
+
+@item info proc mappings
+@kindex info proc mappings
+Report on the address ranges accessible in the program, with information
+on whether your program may read, write, or execute each range.
+
+@item info proc times
+@kindex info proc times
+Starting time, user CPU time, and system CPU time for your program and
+its children.
+
+@item info proc id
+@kindex info proc id
+Report on the process IDs related to your program: its own process ID,
+the ID of its parent, the process group ID, and the session ID.
+
+@item info proc status
+@kindex info proc status
+General information on the state of the process. If the process is
+stopped, this report includes the reason for stopping, and any signal
+received.
+
+@item info proc all
+Show all the above information about the process.
+@end table
+@end ifclear
+
+@node Stopping
+@chapter Stopping and Continuing
+
+The principal purposes of using a debugger are so that you can stop your
+program before it terminates; or so that, if your program runs into
+trouble, you can investigate and find out why.
+
+Inside @value{GDBN}, your program may stop for any of several reasons, such
+as
+@ifclear BARETARGET
+a signal,
+@end ifclear
+a breakpoint, or reaching a new line after a @value{GDBN}
+command such as @code{step}. You may then examine and change
+variables, set new breakpoints or remove old ones, and then continue
+execution. Usually, the messages shown by @value{GDBN} provide ample
+explanation of the status of your program---but you can also explicitly
+request this information at any time.
+
+@table @code
+@item info program
+@kindex info program
+Display information about the status of your program: whether it is
+running or not,
+@ifclear BARETARGET
+what process it is,
+@end ifclear
+and why it stopped.
+@end table
+
+@menu
+@ifclear CONLY
+* Breakpoints:: Breakpoints, watchpoints, and exceptions
+@end ifclear
+@ifset CONLY
+* Breakpoints:: Breakpoints and watchpoints
+@end ifset
+@c Remnant makeinfo bug requires blank line after *successful* end-if in menu:
+
+* Continuing and Stepping:: Resuming execution
+@ifset POSIX
+* Signals:: Signals
+@end ifset
+@end menu
+
+@c makeinfo node-defaulting requires adjacency of @node and sectioning cmds
+@c ...hence distribute @node Breakpoints over two possible @if expansions.
+@c
+@ifclear CONLY
+@node Breakpoints
+@section Breakpoints, watchpoints, and exceptions
+@end ifclear
+@ifset CONLY
+@node Breakpoints
+@section Breakpoints and watchpoints
+@end ifset
+
+@cindex breakpoints
+A @dfn{breakpoint} makes your program stop whenever a certain point in
+the program is reached. For each breakpoint, you can add various
+conditions to control in finer detail whether your program will stop.
+You can set breakpoints with the @code{break} command and its variants
+(@pxref{Set Breaks, ,Setting breakpoints}), to specify the place where
+your program should stop by line number, function name or exact address
+in the program.
+@ifclear CONLY
+In languages with exception handling (such as GNU C++), you can also set
+breakpoints where an exception is raised (@pxref{Exception Handling,
+,Breakpoints and exceptions}).
+@end ifclear
+
+@cindex watchpoints
+@cindex memory tracing
+@cindex breakpoint on memory address
+@cindex breakpoint on variable modification
+A @dfn{watchpoint} is a special breakpoint that stops your program
+when the value of an expression changes. You must use a different
+command to set watchpoints (@pxref{Set Watchpoints, ,Setting
+watchpoints}), but aside from that, you can manage a watchpoint like
+any other breakpoint: you enable, disable, and delete both breakpoints
+and watchpoints using the same commands.
+
+You can arrange to have values from your program displayed automatically
+whenever @value{GDBN} stops at a breakpoint. @xref{Auto Display,
+,Automatic display}.
+
+@cindex breakpoint numbers
+@cindex numbers for breakpoints
+@value{GDBN} assigns a number to each breakpoint or watchpoint when you
+create it; these numbers are successive integers starting with one. 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 your program until you enable it again.
+
+@menu
+* Set Breaks:: Setting breakpoints
+* Set Watchpoints:: Setting watchpoints
+@ifclear CONLY
+* Exception Handling:: Breakpoints and exceptions
+@end ifclear
+
+* Delete Breaks:: Deleting breakpoints
+* Disabling:: Disabling breakpoints
+* Conditions:: Break conditions
+* Break Commands:: Breakpoint command lists
+@ifclear CONLY
+* Breakpoint Menus:: Breakpoint menus
+@end ifclear
+@ifclear BARETARGET
+* Error in Breakpoints:: ``Cannot insert breakpoints''
+@end ifclear
+@end menu
+
+@node Set Breaks
+@subsection Setting breakpoints
+
+@c FIXME LMB what does GDB do if no code on line of breakpt?
+@c consider in particular declaration with/without initialization.
+@c
+@c FIXME 2 is there stuff on this already? break at fun start, already init?
+
+@kindex break
+@kindex b
+@kindex $bpnum
+@cindex latest breakpoint
+Breakpoints are set with the @code{break} command (abbreviated
+@code{b}). The debugger convenience variable @samp{$bpnum} records the
+number of the beakpoint you've set most recently; see @ref{Convenience
+Vars,, Convenience variables}, for a discussion of what you can do with
+convenience variables.
+
+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}.
+@ifclear CONLY
+When using source languages that permit overloading of symbols, such as
+C++, @var{function} may refer to more than one possible place to break.
+@xref{Breakpoint Menus,,Breakpoint menus}, for a discussion of that situation.
+@end ifclear
+
+@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 your 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 your program which do not have debugging
+information or source files.
+
+@item break
+When called without any arguments, @code{break} sets a breakpoint at
+the next instruction to be executed in the selected stack frame
+(@pxref{Stack, ,Examining the Stack}). In any selected frame but the
+innermost, this will cause your program to stop as soon as control
+returns to that frame. This is similar to the effect of a
+@code{finish} command in the frame inside the selected frame---except
+that @code{finish} does not leave an active breakpoint. If you use
+@code{break} without an argument in the innermost frame, @value{GDBN} will stop
+the next time it reaches the current location; this may be useful
+inside loops.
+
+@value{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 your 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---that is, if @var{cond} evaluates as true.
+@samp{@dots{}} stands for one of the possible arguments described
+above (or no argument) specifying where to break. @xref{Conditions,
+,Break 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 for the @code{break} command, and the breakpoint is set in the same
+way, but the breakpoint is automatically disabled after the first time your
+program stops there. @xref{Disabling, ,Disabling breakpoints}.
+
+@item rbreak @var{regex}
+@kindex rbreak
+@cindex regular expression
+@c FIXME what kind of regexp?
+Set breakpoints on all functions matching the regular expression
+@var{regex}. 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 @code{break} command. They can
+be deleted, disabled, made conditional, etc., in the standard ways.
+
+@ifclear CONLY
+When debugging C++ programs, @code{rbreak} is useful for setting
+breakpoints on overloaded functions that are not members of any special
+classes.
+@end ifclear
+
+@kindex info breakpoints
+@cindex @code{$_} and @code{info breakpoints}
+@item info breakpoints @r{[}@var{n}@r{]}
+@itemx info break @r{[}@var{n}@r{]}
+@itemx info watchpoints @r{[}@var{n}@r{]}
+Print a table of all breakpoints and watchpoints set and not
+deleted, with the following columns for each breakpoint:
+
+@table @emph
+@item Breakpoint Numbers
+@item Type
+Breakpoint or watchpoint.
+@item Disposition
+Whether the breakpoint is marked to be disabled or deleted when hit.
+@item Enabled or Disabled
+Enabled breakpoints are marked with @samp{y}. @samp{n} marks breakpoints
+that are not enabled.
+@item Address
+Where the breakpoint is in your program, as a memory address
+@item What
+Where the breakpoint is in the source for your program, as a file and
+line number.
+@end table
+
+@noindent
+If a breakpoint is conditional, @code{info break} shows the condition on
+the line following the affected breakpoint; breakpoint commands, if any,
+are listed after that.
+
+@noindent
+@code{info break} with a breakpoint
+number @var{n} as argument lists only that breakpoint. The
+convenience variable @code{$_} and the default examining-address for
+the @code{x} command are set to the address of the last breakpoint
+listed (@pxref{Memory, ,Examining memory}).
+@end table
+
+@value{GDBN} allows you to set any number of breakpoints at the same place in
+your program. There is nothing silly or meaningless about this. When
+the breakpoints are conditional, this is even useful
+(@pxref{Conditions, ,Break conditions}).
+
+@cindex negative breakpoint numbers
+@cindex internal @value{GDBN} breakpoints
+@value{GDBN} itself sometimes sets breakpoints in your program for special
+purposes, such as proper handling of @code{longjmp} (in C programs).
+These internal breakpoints are assigned negative numbers, starting with
+@code{-1}; @samp{info breakpoints} does not display them.
+
+You can see these breakpoints with the @value{GDBN} maintenance command
+@samp{maint info breakpoints}.
+
+@table @code
+@kindex maint info breakpoints
+@item maint info breakpoints
+Using the same format as @samp{info breakpoints}, display both the
+breakpoints you've set explicitly, and those @value{GDBN} is using for
+internal purposes. Internal breakpoints are shown with negative
+breakpoint numbers. The type column identifies what kind of breakpoint
+is shown:
+
+@table @code
+@item breakpoint
+Normal, explicitly set breakpoint.
+
+@item watchpoint
+Normal, explicitly set watchpoint.
+
+@item longjmp
+Internal breakpoint, used to handle correctly stepping through
+@code{longjmp} calls.
+
+@item longjmp resume
+Internal breakpoint at the target of a @code{longjmp}.
+
+@item until
+Temporary internal breakpoint used by the @value{GDBN} @code{until} command.
+
+@item finish
+Temporary internal breakpoint used by the @value{GDBN} @code{finish} command.
+@end table
+
+@end table
+
+
+@node Set Watchpoints
+@subsection Setting watchpoints
+@cindex setting watchpoints
+
+You can use a watchpoint to stop execution whenever the value of an
+expression changes, without having to predict a particular place
+where this may happen.
+
+Watchpoints currently execute two orders of magnitude more slowly than
+other breakpoints, but this can be well worth it to catch errors where
+you have no clue what part of your program is the culprit. Some
+processors provide special hardware to support watchpoint evaluation; future
+releases of @value{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 watchpoints
+@item info watchpoints
+This command prints a list of watchpoints and breakpoints; it is the
+same as @code{info break}.
+@end table
+
+@ifclear CONLY
+@node Exception Handling
+@subsection Breakpoints and exceptions
+@cindex exception handlers
+
+Some languages, such as GNU C++, implement exception handling. You can
+use @value{GDBN} to examine what caused your program to raise an exception,
+and to list the exceptions your program is prepared to handle at a
+given point in time.
+
+@table @code
+@item catch @var{exceptions}
+@kindex catch
+You can set breakpoints at active exception handlers by using the
+@code{catch} command. @var{exceptions} is a list of names of exceptions
+to catch.
+@end table
+
+You can use @code{info catch} to list active exception handlers.
+@xref{Frame Info, ,Information about a frame}.
+
+There are currently some limitations to exception handling in @value{GDBN}.
+These will be corrected in a future release.
+
+@itemize @bullet
+@item
+If you call a function interactively, @value{GDBN} normally returns
+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 you and cause your program to simply continue
+running until it hits a breakpoint, catches a signal that @value{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 @code{catch} is not the best way to debug exception handling:
+if you need to know exactly where an exception is raised, it is better to
+stop @emph{before} the exception handler is called, since that way you
+can see the stack before any unwinding takes place. If you set a
+breakpoint in an exception handler instead, it may not be easy to find
+out where the exception was raised.
+
+To stop just before an exception handler is called, you need some
+knowledge of the implementation. In the case of GNU C++, exceptions are
+raised by calling a library function named @code{__raise_exception}
+which has the following ANSI C interface:
+
+@example
+ /* @var{addr} is where the exception identifier is stored.
+ ID is the exception identifier. */
+ void __raise_exception (void **@var{addr}, void *@var{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, ,Breakpoints; watchpoints; and exceptions}).
+
+With a conditional breakpoint (@pxref{Conditions, ,Break conditions})
+that depends on the value of @var{id}, you can stop your program when
+a specific exception is raised. You can use multiple conditional
+breakpoints to stop your program when any of a number of exceptions are
+raised.
+@end ifclear
+
+@node Delete Breaks
+@subsection Deleting breakpoints
+
+@cindex clearing breakpoints, watchpoints
+@cindex deleting breakpoints, watchpoints
+It is often necessary to eliminate a breakpoint or watchpoint once it
+has done its job and you no longer want your program to stop there. This
+is called @dfn{deleting} the breakpoint. A breakpoint that has been
+deleted no longer exists; it is forgotten.
+
+With the @code{clear} command you can delete breakpoints according to
+where they are in your program. With the @code{delete} command you can
+delete individual breakpoints or watchpoints by specifying their
+breakpoint numbers.
+
+It is not necessary to delete a breakpoint to proceed past it. @value{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, ,Selecting a frame}). When
+the innermost frame is selected, this is a good way to delete a
+breakpoint where your program just stopped.
+
+@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 @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+@cindex delete breakpoints
+@kindex delete
+@kindex d
+Delete the breakpoints or watchpoints of the numbers specified as
+arguments. If no argument is specified, delete all breakpoints (@value{GDBN}
+asks confirmation, unless you have @code{set confirm off}). You
+can abbreviate this command as @code{d}.
+@end table
+
+@node Disabling
+@subsection Disabling breakpoints
+
+@cindex disabled breakpoints
+@cindex enabled breakpoints
+Rather than deleting a breakpoint or watchpoint, 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 and watchpoints with the
+@code{enable} and @code{disable} commands, optionally specifying one or
+more breakpoint numbers as arguments. Use @code{info break} or
+@code{info watch} to print a list of breakpoints or watchpoints if you
+do not know which numbers to use.
+
+A breakpoint or watchpoint can have any of four different states of
+enablement:
+
+@itemize @bullet
+@item
+Enabled. The breakpoint will stop your program. A breakpoint set
+with the @code{break} command starts out in this state.
+@item
+Disabled. The breakpoint has no effect on your program.
+@item
+Enabled once. The breakpoint will stop your program, but
+when it does so it will become disabled. A breakpoint set
+with the @code{tbreak} command starts out in this state.
+@item
+Enabled for deletion. The breakpoint will stop your program, but
+immediately after it does so it will be deleted permanently.
+@end itemize
+
+You can use the following commands to enable or disable breakpoints and
+watchpoints:
+
+@table @code
+@item disable @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+@kindex disable breakpoints
+@kindex disable
+@kindex dis
+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. You may abbreviate
+@code{disable} as @code{dis}.
+
+@item enable @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+@kindex enable breakpoints
+@kindex enable
+Enable the specified breakpoints (or all defined breakpoints). They
+become effective once again in stopping your program.
+
+@item enable @r{[}breakpoints@r{]} once @var{bnums}@dots{}
+Enable the specified breakpoints temporarily. Each will be disabled
+again the next time it stops your program.
+
+@item enable @r{[}breakpoints@r{]} 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 your program.
+@end table
+
+Save for a breakpoint set with @code{tbreak} (@pxref{Set Breaks,
+,Setting breakpoints}), breakpoints that you set are initially enabled;
+subsequently, they become disabled or enabled only when you use one of
+the commands above. (The command @code{until} can set and delete a
+breakpoint of its own, but it will not change the state of your other
+breakpoints; see @ref{Continuing and Stepping, ,Continuing and
+stepping}.)
+
+@node Conditions
+@subsection Break conditions
+@cindex conditional breakpoints
+@cindex breakpoint conditions
+
+@c FIXME what is scope of break condition expr? Context where wanted?
+@c in particular for a watchpoint?
+The simplest sort of breakpoint breaks every time your 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 (@pxref{Expressions, ,Expressions}). A breakpoint with
+a condition evaluates the expression each time your program reaches it,
+and your program stops only if the condition is @emph{true}.
+
+This is the converse of using assertions for program validation; in that
+situation, you want to stop when the assertion is violated---that is,
+when the condition is false. In C, if you want to test an assertion expressed
+by the condition @var{assert}, you should set the condition
+@samp{! @var{assert}} on the appropriate breakpoint.
+
+Conditions are also accepted for watchpoints; you may not need them,
+since a watchpoint is inspecting the value of an expression anyhow---but
+it might be simpler, say, to just set a watchpoint on a variable name,
+and specify a condition that tests whether the new value is an interesting
+one.
+
+Break conditions can have side effects, and may even call functions in
+your program. This can be useful, for example, to activate functions
+that log program progress, or to use your own print functions to
+format special data structures. The effects are completely predictable
+unless there is another enabled breakpoint at the same address. (In
+that case, @value{GDBN} might see the other breakpoint first and stop your
+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, ,Breakpoint command lists}).
+
+Break conditions can be specified when a breakpoint is set, by using
+@samp{if} in the arguments to the @code{break} command. @xref{Set
+Breaks, ,Setting breakpoints}. They can also be changed at any time
+with the @code{condition} command. The @code{watch} command does not
+recognize the @code{if} keyword; @code{condition} is the only way to
+impose a further condition on a watchpoint.
+
+@table @code
+@item condition @var{bnum} @var{expression}
+@kindex condition
+Specify @var{expression} as the break condition for breakpoint or
+watchpoint number @var{bnum}. From now on, this breakpoint will stop
+your program only if the value of @var{expression} is true (nonzero, in
+C). When you use @code{condition}, @value{GDBN} checks @var{expression}
+immediately for syntactic correctness, and to determine whether symbols
+in it have referents in the context of your breakpoint.
+@c FIXME so what does GDB do if there is no referent? Moreover, what
+@c about watchpoints?
+@value{GDBN} does
+not actually evaluate @var{expression} at the time the @code{condition}
+command is given, however. @xref{Expressions, ,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 your 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, @value{GDBN}
+takes no action.
+
+To make the breakpoint stop the next time it is reached, specify
+a count of zero.
+
+When you use @code{continue} to resume execution of your program from a
+breakpoint, you can specify an ignore count directly as an argument to
+@code{continue}, rather than using @code{ignore}. @xref{Continuing and
+Stepping,,Continuing and stepping}.
+
+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.
+
+You could achieve the effect of the ignore count with a condition such
+as @w{@samp{$foo-- <= 0}} using a debugger convenience variable that
+is decremented each time. @xref{Convenience Vars, ,Convenience
+variables}.
+@end table
+
+@node Break Commands
+@subsection Breakpoint command lists
+
+@cindex breakpoint commands
+You can give any breakpoint (or watchpoint) a series of commands to
+execute when your 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 @r{[}@var{bnum}@r{]}
+@itemx @dots{} @var{command-list} @dots{}
+@itemx end
+@kindex commands
+@kindex end
+Specify a list of commands for breakpoint number @var{bnum}. The commands
+themselves appear on the following lines. Type a line containing just
+@code{end} to terminate the commands.
+
+To remove all commands from a breakpoint, type @code{commands} and
+follow it immediately with @code{end}; that is, give no commands.
+
+With no @var{bnum} argument, @code{commands} refers to the last
+breakpoint or watchpoint set (not to the breakpoint most recently
+encountered).
+@end table
+
+Pressing @key{RET} as a means of repeating the last @value{GDBN} command is
+disabled within a @var{command-list}.
+
+You can use breakpoint commands to start your program up again. Simply
+use the @code{continue} command, or @code{step}, or any other command
+that resumes execution.
+
+Any other commands in the command list, after a command that resumes
+execution, are ignored. This is because any time you resume execution
+(even with a simple @code{next} or @code{step}), you may encounter
+another breakpoint---which could have its own command list, leading to
+ambiguities about which list to execute.
+
+@kindex silent
+If the first command you specify in a command list is @code{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 none of the remaining commands print anything, you
+will see no sign that the breakpoint was reached. @code{silent} is
+meaningful only at the beginning of a breakpoint command list.
+
+The commands @code{echo}, @code{output}, and @code{printf} allow you to
+print precisely controlled output, and are often useful in silent
+breakpoints. @xref{Output, ,Commands for controlled 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.
+
+@example
+break foo if x>0
+commands
+silent
+printf "x is %d\n",x
+cont
+end
+@end example
+
+One application for breakpoint commands is to compensate for one bug so
+you can test for 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 @code{continue} command
+so that your program does not stop, and start with the @code{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
+
+@ifclear CONLY
+@node Breakpoint Menus
+@subsection Breakpoint menus
+@cindex overloading
+@cindex symbol overloading
+
+Some programming languages (notably C++) permit a single function name
+to be defined several times, for application in different contexts.
+This is called @dfn{overloading}. When a function name is overloaded,
+@samp{break @var{function}} is not enough to tell @value{GDBN} where you want
+a breakpoint. If you realize this will be a problem, you can use
+something like @samp{break @var{function}(@var{types})} to specify which
+particular version of the function you want. Otherwise, @value{GDBN} offers
+you a menu of numbered choices for different possible breakpoints, and
+waits for your selection with the prompt @samp{>}. The first two
+options are always @samp{[0] cancel} and @samp{[1] all}. Typing @kbd{1}
+sets a breakpoint at each definition of @var{function}, and typing
+@kbd{0} aborts the @code{break} command without setting any new
+breakpoints.
+
+For example, the following session excerpt shows an attempt to set a
+breakpoint at the overloaded symbol @code{String::after}.
+We choose three particular definitions of that function name:
+
+@c FIXME! This is likely to change to show arg type lists, at least
+@smallexample
+(@value{GDBP}) b String::after
+[0] cancel
+[1] all
+[2] file:String.cc; line number:867
+[3] file:String.cc; line number:860
+[4] file:String.cc; line number:875
+[5] file:String.cc; line number:853
+[6] file:String.cc; line number:846
+[7] file:String.cc; line number:735
+> 2 4 6
+Breakpoint 1 at 0xb26c: file String.cc, line 867.
+Breakpoint 2 at 0xb344: file String.cc, line 875.
+Breakpoint 3 at 0xafcc: file String.cc, line 846.
+Multiple breakpoints were set.
+Use the "delete" command to delete unwanted
+ breakpoints.
+(@value{GDBP})
+@end smallexample
+@end ifclear
+
+@ifclear BARETARGET
+@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
+@c some light may be shed by looking at instances of
+@c ONE_PROCESS_WRITETEXT. But error message seems possible otherwise
+@c too. pesch, 20sep91
+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 causes @value{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 @value{GDBN}, and copy the file containing your program to a new name.
+Resume @value{GDBN} and use the @code{exec-file} command to specify that @value{GDBN}
+should run your program under that name. Then start your program again.
+
+@c FIXME: RMS commented here "Show example". Maybe when someone
+@c explains the first FIXME: in this section...
+
+@item
+Relink your 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
+@end ifclear
+
+@node Continuing and Stepping
+@section Continuing and stepping
+
+@cindex stepping
+@cindex continuing
+@cindex resuming execution
+@dfn{Continuing} means resuming program execution until your program
+completes normally. In contrast, @dfn{stepping} means executing just
+one more ``step'' of your program, where ``step'' may mean either one
+line of source code, or one machine instruction (depending on what
+particular command you use). Either when continuing
+or when stepping, your program may stop even sooner, due to
+@ifset BARETARGET
+a breakpoint.
+@end ifset
+@ifclear BARETARGET
+a breakpoint or a signal. (If due to a signal, you may want to use
+@code{handle}, or use @samp{signal 0} to resume execution.
+@xref{Signals, ,Signals}.)
+@end ifclear
+
+@table @code
+@item continue @r{[}@var{ignore-count}@r{]}
+@itemx c @r{[}@var{ignore-count}@r{]}
+@itemx fg @r{[}@var{ignore-count}@r{]}
+@kindex continue
+@kindex c
+@kindex fg
+Resume program execution, at the address where your program last stopped;
+any breakpoints set at that address are bypassed. The optional argument
+@var{ignore-count} allows you to specify a further number of times to
+ignore a breakpoint at this location; its effect is like that of
+@code{ignore} (@pxref{Conditions, ,Break conditions}).
+
+The argument @var{ignore-count} is meaningful only when your program
+stopped due to a breakpoint. At other times, the argument to
+@code{continue} is ignored.
+
+The synonyms @code{c} and @code{fg} are provided purely for convenience,
+and have exactly the same behavior as @code{continue}.
+@end table
+
+To resume execution at a different place, you can use @code{return}
+(@pxref{Returning, ,Returning from a function}) to go back to the
+calling function; or @code{jump} (@pxref{Jumping, ,Continuing at a
+different address}) to go to an arbitrary location in your program.
+
+A typical technique for using stepping is to set a breakpoint
+@ifclear CONLY
+(@pxref{Breakpoints, ,Breakpoints; watchpoints; and exceptions})
+@end ifclear
+@ifset CONLY
+(@pxref{Breakpoints, ,Breakpoints and watchpoints})
+@end ifset
+at the
+beginning of the function or the section of your program where a
+problem is believed to lie, run your 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.
+
+@table @code
+@item step
+@kindex step
+@kindex s
+Continue running your program until control reaches a different source
+line, then stop it and return control to @value{GDBN}. This command is
+abbreviated @code{s}.
+
+@quotation
+@emph{Warning:} If you use the @code{step} command while control is
+within a function that was compiled without debugging information,
+execution proceeds until control reaches a function that does have
+debugging information.
+@end quotation
+
+@item step @var{count}
+Continue running as in @code{step}, but do so @var{count} times. If a
+breakpoint is reached,
+@ifclear BARETARGET
+or a signal not related to stepping occurs before @var{count} steps,
+@end ifclear
+stepping stops right away.
+
+@item next @r{[}@var{count}@r{]}
+@kindex next
+@kindex n
+Continue to the next source line in the current (innermost) stack frame.
+Similar to @code{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 @code{next} command was given. This command is abbreviated
+@code{n}.
+
+An argument @var{count} is a repeat count, as for @code{step}.
+
+@code{next} within a function that lacks debugging information acts like
+@code{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 function in the selected stack frame
+returns. Print the returned value (if any).
+
+Contrast this with the @code{return} command (@pxref{Returning,
+,Returning from a function}).
+
+@item until
+@kindex until
+@itemx u
+@kindex u
+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 @code{next}
+command, except that when @code{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, @code{until} will cause your program to continue execution
+until the loop is exited. In contrast, a @code{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.
+
+@code{until} always stops your program if it attempts to exit the current
+stack frame.
+
+@code{until} may produce somewhat counterintuitive results if the order
+of machine code does not match the order of the source lines. For
+example, in the following excerpt from a debugging session, the @code{f}
+(@code{frame}) command shows that execution is stopped at line
+@code{206}; yet when we use @code{until}, we get to line @code{195}:
+
+@example
+(@value{GDBP}) f
+#0 main (argc=4, argv=0xf7fffae8) at m4.c:206
+206 expand_input();
+(@value{GDBP}) until
+195 for ( ; argc > 0; NEXTARG) @{
+@end example
+
+This happened because, for execution efficiency, the compiler had
+generated code for the loop closure test at the end, rather than the
+start, of the loop---even though the test in a C @code{for}-loop is
+written before the body of the loop. The @code{until} command appeared
+to step back to the beginning of the loop when it advanced to this
+expression; however, it has not really gone to an earlier
+statement---not in terms of the actual machine code.
+
+@code{until} with no argument works by means of single
+instruction stepping, and hence is slower than @code{until} with an
+argument.
+
+@item until @var{location}
+@itemx u @var{location}
+Continue running your program until either the specified location is
+reached, or the current stack frame returns. @var{location} is any of
+the forms of argument acceptable to @code{break} (@pxref{Set Breaks,
+,Setting breakpoints}). This form of the command uses breakpoints,
+and hence is quicker than @code{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,
+,Automatic display}.
+
+An argument is a repeat count, as in @code{step}.
+
+@need 750
+@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 @code{next}.
+@end table
+
+@ifset POSIX
+@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 an interrupt (often @kbd{C-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 your program has
+requested an alarm).
+
+@cindex fatal signals
+Some signals, including @code{SIGALRM}, are a normal part of the
+functioning of your program. Others, such as @code{SIGSEGV}, indicate
+errors; these signals are @dfn{fatal} (kill your 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 your program, but it is normally
+fatal so it can carry out the purpose of the interrupt: to kill the program.
+
+@value{GDBN} has the ability to detect any occurrence of a signal in your
+program. You can tell @value{GDBN} in advance what to do for each kind of
+signal.
+
+@cindex handling signals
+Normally, @value{GDBN} is set up to ignore non-erroneous signals like @code{SIGALRM}
+(so as not to interfere with their role in the functioning of your program)
+but to stop your program immediately whenever an error signal happens.
+You can change these settings with the @code{handle} command.
+
+@table @code
+@item info signals
+@kindex info signals
+Print a table of all the kinds of signals and how @value{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 @value{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
+
+@c @group
+The keywords allowed by the @code{handle} command can be abbreviated.
+Their full names are:
+
+@table @code
+@item nostop
+@value{GDBN} should not stop your program when this signal happens. It may
+still print a message telling you that the signal has come in.
+
+@item stop
+@value{GDBN} should stop your program when this signal happens. This implies
+the @code{print} keyword as well.
+
+@item print
+@value{GDBN} should print a message when this signal happens.
+
+@item noprint
+@value{GDBN} should not mention the occurrence of the signal at all. This
+implies the @code{nostop} keyword as well.
+
+@item pass
+@value{GDBN} should allow your program to see this signal; your program will be
+able to handle the signal, or may be terminated if the signal is fatal
+and not handled.
+
+@item nopass
+@value{GDBN} should not allow your program to see this signal.
+@end table
+@c @end group
+
+When a signal stops your program, the signal is not visible until you
+continue. Your program will see the signal then, if @code{pass} is in
+effect for the signal in question @emph{at that time}. In other words,
+after @value{GDBN} reports a signal, you can use the @code{handle}
+command with @code{pass} or @code{nopass} to control whether that
+signal will be seen by your program when you later continue it.
+
+You can also use the @code{signal} command to prevent your 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. For example, if your 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 your program would probably terminate immediately as
+a result of the fatal signal once it saw the signal. To prevent this,
+you can continue with @samp{signal 0}. @xref{Signaling, ,Giving your
+program a signal}.
+@end ifset
+
+@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 your 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 @value{GDBN} commands for examining the
+stack allow you to see all of this information.
+
+@cindex selected frame
+One of the stack frames is @dfn{selected} by @value{GDBN} and many
+@value{GDBN} commands refer implicitly to the selected frame. In
+particular, whenever you ask @value{GDBN} for the value of a variable in
+your program, the value is found in the selected frame. There are
+special @value{GDBN} commands to select whichever frame you are
+interested in.
+
+When your program stops, @value{GDBN} automatically selects the
+currently executing frame and describes it briefly as the @code{frame}
+command does (@pxref{Frame Info, ,Information about a frame}).
+
+@menu
+* Frames:: Stack frames
+* Backtrace:: Backtraces
+* Selection:: Selecting a frame
+* Frame Info:: Information on a frame
+@ifset MIPS
+* MIPS Stack:: MIPS machines and the function stack
+@end ifset
+@end menu
+
+@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
+@value{GDBN} assigns numbers to all existing stack frames, starting with
+zero for the innermost frame, one for the frame that called it,
+and so on upward. These numbers do not really exist in your program;
+they are assigned by @value{GDBN} to give you a way of designating stack
+frames in @value{GDBN} commands.
+
+@c below produces an acceptable overful hbox. --mew 13aug1993
+@cindex frameless execution
+Some compilers provide a way to compile functions so that they operate
+without stack frames. (For example, the @code{@value{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. @value{GDBN} has limited facilities for dealing
+with these function invocations. If the innermost function invocation
+has no stack frame, @value{GDBN} will nevertheless regard it as though
+it had a separate frame, which is numbered zero as usual, allowing
+correct tracing of the function call chain. However, @value{GDBN} has
+no provision for frameless functions elsewhere in the stack.
+
+@node Backtrace
+@section Backtraces
+
+A backtrace is a summary of how your 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{C-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
+@kindex info s
+The names @code{where} and @code{info stack} (abbreviated @code{info s})
+are additional aliases for @code{backtrace}.
+
+Each line in the backtrace shows the frame number and the function name.
+The program counter value is also shown---unless you use @code{set
+print address off}. The backtrace also shows the source file name and
+line number, as well as the arguments to the function. 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.
+
+@smallexample
+@group
+#0 m4_traceon (obs=0x24eb0, argc=1, argv=0x2b8c8)
+ at builtin.c:993
+#1 0x6e38 in expand_macro (sym=0x2b600) at macro.c:242
+#2 0x6840 in expand_token (obs=0x0, t=177664, td=0xf7fffb08)
+ at macro.c:71
+(More stack frames follow...)
+@end group
+@end smallexample
+
+@noindent
+The display for frame zero does not begin with a program counter
+value, indicating that your program has stopped at the beginning of the
+code for line @code{993} of @code{builtin.c}.
+
+@node Selection
+@section Selecting a frame
+
+Most commands for examining the stack and other data in your 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}
+@itemx f @var{n}
+@kindex frame
+@kindex f
+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 the one for
+@code{main}.
+
+@item frame @var{addr}
+@itemx f @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 @value{GDBN} to assign numbers properly to all frames. In
+addition, this can be useful when your program has multiple stacks and
+switches between them.
+
+@ifset SPARC
+On the SPARC architecture, @code{frame} needs two addresses to
+select an arbitrary frame: a frame pointer and a stack pointer.
+@c note to future updaters: this is conditioned on a flag
+@c FRAME_SPECIFICATION_DYADIC in the tm-*.h files, currently only used
+@c by SPARC, hence the specific attribution. Generalize or list all
+@c possibilities if more supported machines start doing this.
+@end ifset
+
+@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
+@kindex do
+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. You may
+abbreviate @code{down} as @code{do}.
+@end table
+
+All of these commands end by printing two lines of output describing the
+frame. The first line shows the frame number, the function name, the
+arguments, and the source file and line number of execution in that
+frame. The second line shows the text of that source line.
+
+For example:
+@smallexample
+@group
+(@value{GDBP}) up
+#1 0x22f0 in main (argc=1, argv=0xf7fffbf4, env=0xf7fffbfc)
+ at env.c:10
+10 read_input_file (argv[i]);
+@end group
+@end smallexample
+
+After such a printout, the @code{list} command with no arguments will
+print ten lines centered on the point of execution in the frame.
+@xref{List, ,Printing source lines}.
+
+@table @code
+@item up-silently @var{n}
+@itemx down-silently @var{n}
+@kindex down-silently
+@kindex up-silently
+These two commands are variants of @code{up} and @code{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 @value{GDBN} command scripts, where the output might be unnecessary and
+distracting.
+@end table
+
+@node Frame Info
+@section Information about a frame
+
+There are several other commands to print information about the selected
+stack frame.
+
+@table @code
+@item frame
+@itemx f
+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 @code{f}. With an
+argument, this command is used to select a stack frame.
+@xref{Selection, ,Selecting a frame}.
+
+@item info frame
+@itemx info f
+@kindex info frame
+@kindex info f
+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
+language that the source code corresponding to this frame was written in,
+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}
+@itemx info f @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 either static or automatic)
+accessible at the point of execution of the selected frame.
+
+@ifclear CONLY
+@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 @code{up},
+@code{down}, or @code{frame} commands); then type @code{info catch}.
+@xref{Exception Handling, ,Breakpoints and exceptions}.
+@end ifclear
+@end table
+
+@ifset MIPS
+@node MIPS Stack
+@section MIPS machines and the function stack
+
+@cindex stack on MIPS
+@cindex MIPS stack
+MIPS based computers use an unusual stack frame, which sometimes
+requires @value{GDBN} to search backward in the object code to find the
+beginning of a function.
+
+@cindex response time, MIPS debugging
+To improve response time (especially for embedded applications, where
+@value{GDBN} may be restricted to a slow serial line for this search)
+you may want to limit the size of this search, using one of these
+commands:
+@c FIXME! So what happens when GDB does *not* find the beginning of a
+@c function?
+
+@cindex @code{heuristic-fence-post} (MIPS)
+@table @code
+@item set heuristic-fence-post @var{limit}
+Restrict @var{GDBN} to examining at most @var{limit} bytes in its search
+for the beginning of a function. A value of @code{0} (the default)
+means there is no limit.
+
+@item show heuristic-fence-post
+Display the current limit.
+@end table
+
+@noindent
+These commands are available @emph{only} when @value{GDBN} is configured
+for debugging programs on MIPS processors.
+@end ifset
+
+@node Source
+@chapter Examining Source Files
+
+@value{GDBN} can print parts of your program's source, since the debugging
+information recorded in the program tells @value{GDBN} what source files were
+used to build it. When your program stops, @value{GDBN} spontaneously prints
+the line where it stopped. Likewise, when you select a stack frame
+(@pxref{Selection, ,Selecting a frame}), @value{GDBN} prints the line where
+execution in that frame has stopped. You can print other portions of
+source files by explicit command.
+
+@ifclear DOSHOST
+If you use @value{GDBN} through its GNU Emacs interface, you may prefer to use
+Emacs facilities to view source; @pxref{Emacs, ,Using @value{GDBN} under GNU
+Emacs}.
+@end ifclear
+
+@menu
+* List:: Printing source lines
+@ifclear DOSHOST
+* Search:: Searching source files
+@end ifclear
+
+* Source Path:: Specifying source directories
+* Machine Code:: Source and machine code
+@end menu
+
+@node List
+@section Printing source lines
+
+@kindex list
+@kindex l
+To print lines from a source file, use the @code{list} command
+(abbreviated @code{l}). There are several ways to specify what part
+of the file you want to print.
+
+Here are the forms of the @code{list} command most commonly used:
+
+@table @code
+@item list @var{linenum}
+Print lines centered around line number @var{linenum} in the
+current source file.
+
+@item list @var{function}
+Print lines centered around the beginning of function
+@var{function}.
+
+@item list
+Print more lines. If the last lines printed were printed with a
+@code{list} command, this prints 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, ,Examining the
+Stack}), this prints lines centered around that line.
+
+@item list -
+Print lines just before the lines last printed.
+@end table
+
+By default, @value{GDBN} prints ten source lines with any of these forms of
+the @code{list} command. You can change this using @code{set listsize}:
+
+@table @code
+@item set listsize @var{count}
+@kindex set listsize
+Make the @code{list} command display @var{count} source lines (unless
+the @code{list} argument explicitly specifies some other number).
+
+@item show listsize
+@kindex show listsize
+Display the number of lines that @code{list} will currently display by
+default.
+@end table
+
+Repeating a @code{list} command with @key{RET} discards the argument,
+so it is equivalent to typing just @code{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 @code{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 @code{list}:
+
+@table @code
+@item list @var{linespec}
+Print 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 lines ending with @var{last}.
+
+@item list @var{first},
+Print lines starting with @var{first}.
+
+@item list +
+Print lines just after the lines last printed.
+
+@item list -
+Print 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{number}
+Specifies line @var{number} of the current source file.
+When a @code{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 @code{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{number}
+Specifies line @var{number} in the source file @var{filename}.
+
+@item @var{function}
+@c FIXME: "of the open-brace" is C-centric. When we add other langs...
+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}. You only need the
+file name with a function name to avoid ambiguity when there are
+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
+
+@ifclear DOSHOST
+@node Search
+@section Searching source files
+@cindex searching
+@kindex reverse-search
+
+There are two commands for searching through the current source file for a
+regular expression.
+
+@table @code
+@item forward-search @var{regexp}
+@itemx search @var{regexp}
+@kindex search
+@kindex forward-search
+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 use
+synonym @samp{search @var{regexp}} or abbreviate the command name as
+@code{fo}.
+
+@item reverse-search @var{regexp}
+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 as @code{rev}.
+@end table
+@end ifclear
+
+@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. @value{GDBN} has a list of directories to search for source files;
+this is called the @dfn{source path}. Each time @value{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 @value{GDBN} cannot find a source file in the source path, and the object
+program records a directory, @value{GDBN} tries that directory too. If the
+source path is empty, and there is no record of the compilation
+directory, @value{GDBN} will, as a last resort, look in the current
+directory.
+
+Whenever you reset or rearrange the source path, @value{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 @value{GDBN}, its source path is empty.
+To add other directories, use the @code{directory} command.
+
+@table @code
+@item directory @var{dirname} @dots{}
+Add directory @var{dirname} to the front of the source path. Several
+directory names may be given to this command, separated by @samp{:} or
+whitespace. You may specify a directory that is already in the source
+path; this moves it forward, so it will be searched sooner.
+
+@kindex cdir
+@kindex cwd
+@kindex $cdir
+@kindex $cwd
+@cindex compilation directory
+@cindex current directory
+@cindex working directory
+@cindex directory, current
+@cindex directory, compilation
+You can use the string @samp{$cdir} to refer to the compilation
+directory (if one is recorded), and @samp{$cwd} to refer to the current
+working directory. @samp{$cwd} is not the same as @samp{.}---the former
+tracks the current working directory as it changes during your @value{GDBN}
+session, while the latter is immediately expanded to the current
+directory at the time you add an entry to the source path.
+
+@item directory
+Reset the source path to empty again. This requires confirmation.
+
+@c RET-repeat for @code{directory} is explicitly disabled, but since
+@c repeating it would be a no-op we do not say that. (thanks to RMS)
+
+@item show directories
+@kindex show 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, @value{GDBN} may sometimes cause confusion by finding the wrong
+versions of source. You can correct the situation as follows:
+
+@enumerate
+@item
+Use @code{directory} with no argument to reset the source path to empty.
+
+@item
+Use @code{directory} with suitable arguments to reinstall the
+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 @code{info line} to map source lines to program
+addresses (and vice versa), and the command @code{disassemble} 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}. You can specify source lines in any of
+the ways understood by the @code{list} command (@pxref{List, ,Printing
+source lines}).
+@end table
+
+For example, we can use @code{info line} to discover the location of
+the object code for the first line of function
+@code{m4_changequote}:
+
+@smallexample
+(@value{GDBP}) info line m4_changecom
+Line 895 of "builtin.c" starts at pc 0x634c and ends at 0x6350.
+@end smallexample
+
+@noindent
+We can also inquire (using @code{*@var{addr}} as the form for
+@var{linespec}) what source line covers a particular address:
+@smallexample
+(@value{GDBP}) info line *0x63ff
+Line 926 of "builtin.c" starts at pc 0x63e4 and ends at 0x6404.
+@end smallexample
+
+@cindex @code{$_} and @code{info line}
+After @code{info line}, the default address for the @code{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,
+,Examining memory}). Also, this address is saved as the value of the
+convenience variable @code{$_} (@pxref{Convenience Vars, ,Convenience
+variables}).
+
+@table @code
+@kindex disassemble
+@item disassemble
+@cindex assembly instructions
+@cindex instructions, assembly
+@cindex machine instructions
+@cindex listing machine instructions
+This specialized command dumps 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 specify a range of addresses (first
+inclusive, second exclusive) to dump.
+@end table
+
+@ifclear H8EXCLUSIVE
+We can use @code{disassemble} to inspect the object code
+range shown in the last @code{info line} example (the example
+shows SPARC machine instructions):
+
+
+@smallexample
+(@value{GDBP}) disas 0x63e4 0x6404
+Dump of assembler code from 0x63e4 to 0x6404:
+0x63e4 <builtin_init+5340>: ble 0x63f8 <builtin_init+5360>
+0x63e8 <builtin_init+5344>: sethi %hi(0x4c00), %o0
+0x63ec <builtin_init+5348>: ld [%i1+4], %o0
+0x63f0 <builtin_init+5352>: b 0x63fc <builtin_init+5364>
+0x63f4 <builtin_init+5356>: ld [%o0+4], %o0
+0x63f8 <builtin_init+5360>: or %o0, 0x1a4, %o0
+0x63fc <builtin_init+5364>: call 0x9288 <path_search>
+0x6400 <builtin_init+5368>: nop
+End of assembler dump.
+@end smallexample
+@end ifclear
+
+@ifset H8EXCLUSIVE
+For example, here is the beginning of the output for the
+disassembly of a function @code{fact}:
+
+
+@smallexample
+(@value{GDBP}) disas fact
+Dump of assembler code for function fact:
+to 0x808c:
+0x802c <fact>: 6d f2 mov.w r2,@@-r7
+0x802e <fact+2>: 6d f3 mov.w r3,@@-r7
+0x8030 <fact+4>: 6d f6 mov.w r6,@@-r7
+0x8032 <fact+6>: 0d 76 mov.w r7,r6
+0x8034 <fact+8>: 6f 70 00 08 mov.w @@(0x8,r7),r0
+0x8038 <fact+12> 19 11 sub.w r1,r1
+ .
+ .
+ .
+@end smallexample
+@end ifset
+
+@node Data
+@chapter Examining Data
+
+@cindex printing data
+@cindex examining data
+@kindex print
+@kindex inspect
+@c "inspect" is not quite a synonym if you are using Epoch, which we do not
+@c document because it is 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 @code{print}
+command (abbreviated @code{p}), or its synonym @code{inspect}.
+@ifclear CONLY
+It evaluates and prints the value of an expression of the language your
+program is written in (@pxref{Languages, ,Using @value{GDBN} with Different
+Languages}).
+@end ifclear
+
+@table @code
+@item print @var{exp}
+@itemx print /@var{f} @var{exp}
+@var{exp} is an expression (in the source language). By default the
+value of @var{exp} is printed in a format appropriate to its data type;
+you can choose a different format by specifying @samp{/@var{f}}, where
+@var{f} is a letter specifying the format; @pxref{Output Formats,,Output
+formats}.
+
+@item print
+@itemx print /@var{f}
+If you omit @var{exp}, @value{GDBN} displays the last value again (from the
+@dfn{value history}; @pxref{Value History, ,Value history}). This allows you to
+conveniently inspect the same value in an alternative format.
+@end table
+
+A more low-level way of examining data is with the @code{x} command.
+It examines data in memory at a specified address and prints it in a
+specified format. @xref{Memory, ,Examining memory}.
+
+If you are interested in information about types, or about how the fields
+of a struct
+@ifclear CONLY
+or class
+@end ifclear
+are declared, use the @code{ptype @var{exp}}
+command rather than @code{print}. @xref{Symbols, ,Examining the Symbol Table}.
+
+@menu
+* Expressions:: Expressions
+* Variables:: Program variables
+* Arrays:: Artificial arrays
+* Output Formats:: Output formats
+* Memory:: Examining memory
+* Auto Display:: Automatic display
+* Print Settings:: Print settings
+* Value History:: Value history
+* Convenience Vars:: Convenience variables
+* Registers:: Registers
+@ifclear HAVE-FLOAT
+* Floating Point Hardware:: Floating point hardware
+@end ifclear
+@end menu
+
+@node Expressions
+@section Expressions
+
+@cindex expressions
+@code{print} and many other @value{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 valid in an expression in
+@value{GDBN}. This includes conditional expressions, function calls, casts
+and string constants. It unfortunately does not include symbols defined
+by preprocessor @code{#define} commands.
+
+@ifclear CONLY
+Because C is so widespread, most of the expressions shown in examples in
+this manual are in C. @xref{Languages, , Using @value{GDBN} with Different
+Languages}, for information on how to use expressions in other
+languages.
+
+In this section, we discuss operators that you can use in @value{GDBN}
+expressions regardless of your programming language.
+
+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.
+@c FIXME: casts supported---Mod2 true?
+@end ifclear
+
+@value{GDBN} supports these operators in addition to those of programming
+languages:
+
+@table @code
+@item @@
+@samp{@@} is a binary operator for treating parts of memory as arrays.
+@xref{Arrays, ,Artificial arrays}, for more information.
+
+@item ::
+@samp{::} allows you to specify a variable in terms of the file or
+function where it is defined. @xref{Variables, ,Program variables}.
+
+@item @{@var{type}@} @var{addr}
+@cindex @{@var{type}@}
+@cindex type casting memory
+@cindex memory, viewing as typed object
+@cindex casts, to view memory
+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 binary operators, just as in
+a cast). This construct is allowed regardless of what kind of data is
+normally supposed to reside at @var{addr}.
+@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, ,Selecting a frame}); 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
+you can examine and use the variable @code{a} whenever your program is
+executing within the function @code{foo}, but you can only use or
+examine the variable @code{b} while your program is executing inside
+the block where @code{b} is declared.
+
+@cindex variable name conflict
+There is an 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). If that
+happens, referring to that name has unpredictable effects. If you wish,
+you can specify a static variable in a particular function or file,
+using the colon-colon notation:
+
+@cindex colon-colon
+@iftex
+@c info cannot cope with a :: index entry, but why deprive hard copy readers?
+@kindex ::
+@end iftex
+@example
+@var{file}::@var{variable}
+@var{function}::@var{variable}
+@end example
+
+@noindent
+Here @var{file} or @var{function} is the name of the context for the
+static @var{variable}. In the case of file names, you can use quotes to
+make sure @value{GDBN} parses the file name as a single word---for example,
+to print a global value of @code{x} defined in @file{f2.c}:
+
+@example
+(@value{GDBP}) p 'f2.c'::x
+@end example
+
+@ifclear CONLY
+@cindex C++ scope resolution
+This use of @samp{::} is very rarely in conflict with the very similar
+use of the same notation in C++. @value{GDBN} also supports use of the C++
+scope resolution operator in @value{GDBN} expressions.
+@c FIXME: Um, so what happens in one of those rare cases where it's in
+@c conflict?? --mew
+@end ifclear
+
+@cindex wrong values
+@cindex variable values, wrong
+@quotation
+@emph{Warning:} Occasionally, a local variable may appear to have the
+wrong value at certain points in a function---just after entry to a new
+scope, and just before exit.
+@end quotation
+You may see this problem when you are stepping by machine instructions.
+This is because on most machines, it takes more than one instruction to
+set up a stack frame (including local variable definitions); if you are
+stepping by machine instructions, variables may appear to have the wrong
+values until the stack frame is completely built. On exit, it usually
+also takes more than one machine instruction to destroy a stack frame;
+after you begin stepping through that group of instructions, local
+variable definitions may be gone.
+
+@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.
+
+You can do this by referring to a contiguous span of memory as an
+@dfn{artificial array}, using 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 desired 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.
+Artificial arrays most often appear in expressions via the value history
+(@pxref{Value History, ,Value history}), after printing one out.
+
+Sometimes the artificial array mechanism is not quite enough; in
+moderately complex data structures, the elements of interest may not
+actually be adjacent---for example, if you are interested in the values
+of pointers in an array. One useful work-around in this situation is
+to use a convenience variable (@pxref{Convenience Vars, ,Convenience
+variables}) as a counter in an expression that prints the first
+interesting value, and then repeat that expression via @key{RET}. For
+instance, suppose you have an array @code{dtab} of pointers to
+structures, and you are interested in the values of a field @code{fv}
+in each structure. Here is an example of what you might type:
+
+@example
+set $i = 0
+p dtab[$i++]->fv
+@key{RET}
+@key{RET}
+@dots{}
+@end example
+
+@node Output Formats
+@section Output formats
+
+@cindex formatted output
+@cindex output formats
+By default, @value{GDBN} prints a value according to its data type. 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 as 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
+@code{print} command with a slash and a format letter. The format
+letters supported are:
+
+@table @code
+@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 t
+Print as integer in binary. The letter @samp{t} stands for ``two''.
+@footnote{@samp{b} cannot be used because these format letters are also
+used with the @code{x} command, where @samp{b} stands for ``byte'';
+@pxref{Memory,,Examining memory}.}
+
+@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
+(@value{GDBP}) p/a 0x54320
+$3 = 0x54320 <_initialize_vx+396>
+@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 @value{GDBN} cannot contain a slash.
+
+To reprint the last value in the value history with a different format,
+you can use the @code{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
+
+You can use the command @code{x} (for ``examine'') to examine memory in
+any of several formats, independently of your program's data types.
+
+@cindex examining memory
+@table @code
+@kindex x
+@item x/@var{nfu} @var{addr}
+@itemx x @var{addr}
+@itemx x
+Use the @code{x} command to examine memory.
+@end table
+
+@var{n}, @var{f}, and @var{u} are all optional parameters that specify how
+much memory to display and how to format it; @var{addr} is an
+expression giving the address where you want to start displaying memory.
+If you use defaults for @var{nfu}, you need not type the slash @samp{/}.
+Several commands set convenient defaults for @var{addr}.
+
+@table @r
+@item @var{n}, the repeat count
+The repeat count is a decimal integer; the default is 1. It specifies
+how much memory (counting by units @var{u}) to display.
+@c This really is **decimal**; unaffected by 'set radix' as of GDB
+@c 4.1.2.
+
+@item @var{f}, the display format
+The display format is one of the formats used by @code{print},
+or @samp{s} (null-terminated string) or @samp{i} (machine instruction).
+The default is @samp{x} (hexadecimal) initially, or the format from the
+last time you used either @code{x} or @code{print}.
+
+@item @var{u}, the unit size
+The unit size is any of
+
+@table @code
+@item b
+Bytes.
+@item h
+Halfwords (two bytes).
+@item w
+Words (four bytes). This is the initial default.
+@item g
+Giant words (eight bytes).
+@end table
+
+Each time you specify a unit size with @code{x}, that size becomes the
+default unit the next time you use @code{x}. (For the @samp{s} and
+@samp{i} formats, the unit size is ignored and is normally not written.)
+
+@item @var{addr}, starting display address
+@var{addr} is the address where you want @value{GDBN} to begin displaying
+memory. The expression need not have a pointer value (though it may);
+it is always interpreted as an integer address of a byte of memory.
+@xref{Expressions, ,Expressions}, for more information on expressions. The default for
+@var{addr} is usually just after the last address examined---but several
+other commands also set the default address: @code{info breakpoints} (to
+the address of the last breakpoint listed), @code{info line} (to the
+starting address of a line), and @code{print} (if you use it to display
+a value from memory).
+@end table
+
+For example, @samp{x/3uh 0x54320} is a request to display three halfwords
+(@code{h}) of memory, formatted as unsigned decimal integers (@samp{u}),
+starting at address @code{0x54320}. @samp{x/4xw $sp} prints the four
+words (@samp{w}) of memory above the stack pointer (here, @samp{$sp};
+@pxref{Registers}) in hexadecimal (@samp{x}).
+
+Since the letters indicating unit sizes are all distinct from the
+letters specifying output formats, you do not have to remember whether
+unit size or format comes first; either order will work. The output
+specifications @samp{4xw} and @samp{4wx} mean exactly the same thing.
+(However, the count @var{n} must come first; @samp{wx4} will not work.)
+
+Even though the unit size @var{u} is ignored for the formats @samp{s}
+and @samp{i}, you might still want to use a count @var{n}; for example,
+@samp{3i} specifies that you want to see three machine instructions,
+including any operands. The command @code{disassemble} gives an
+alternative way of inspecting machine instructions; @pxref{Machine
+Code,,Source and machine code}.
+
+All the defaults for the arguments to @code{x} are designed to make it
+easy to continue scanning memory with minimal specifications each time
+you use @code{x}. For example, after you have inspected three machine
+instructions with @samp{x/3i @var{addr}}, you can inspect the next seven
+with just @samp{x/7}. If you use @key{RET} to repeat the @code{x} command,
+the repeat count @var{n} is used again; the other arguments default as
+for successive uses of @code{x}.
+
+@cindex @code{$_}, @code{$__}, and value history
+The addresses and contents printed by the @code{x} command are not saved
+in the value history because there is often too much of them and they
+would get in the way. Instead, @value{GDBN} makes these values available for
+subsequent use in expressions as values of the convenience variables
+@code{$_} and @code{$__}. After an @code{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 @code{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 @value{GDBN} will print its value each time your 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
+This display shows item numbers, expressions and their current values. As with
+displays you request manually using @code{x} or @code{print}, you can
+specify the output format you prefer; in fact, @code{display} decides
+whether to use @code{print} or @code{x} depending on how elaborate your
+format specification is---it uses @code{x} if you specify a unit size,
+or one of the two formats (@samp{i} and @samp{s}) that are only
+supported by @code{x}; otherwise it uses @code{print}.
+
+@table @code
+@item display @var{exp}
+@kindex display
+Add the expression @var{exp} to the list of expressions to display
+each time your program stops. @xref{Expressions, ,Expressions}.
+
+@code{display} will not repeat if you press @key{RET} again after using it.
+
+@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
+arrange to display it each time in the specified format @var{fmt}.
+@xref{Output Formats,,Output formats}.
+
+@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 your program stops. Examining means in effect
+doing @samp{x/@var{fmt} @var{addr}}. @xref{Memory, ,Examining 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.
+
+@code{undisplay} will not repeat if you press @key{RET} after using it.
+(Otherwise you would just get the error @samp{No display number @dots{}}.)
+
+@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 your 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
+@code{display last_char} while inside a function with an argument
+@code{last_char}, then this argument will be displayed while your program
+continues to stop inside that function. When it stops elsewhere---where
+there is no variable @code{last_char}---display is disabled. The next time
+your program stops where @code{last_char} is meaningful, you can enable the
+display expression once again.
+
+@node Print Settings
+@section Print settings
+
+@cindex format options
+@cindex print settings
+@value{GDBN} provides the following ways to control how arrays, structures,
+and symbols are printed.
+
+@noindent
+These settings are useful for debugging programs in any language:
+
+@table @code
+@item set print address
+@itemx set print address on
+@kindex set print address
+@value{GDBN} will print memory addresses showing the location of stack
+traces, structure values, pointer values, breakpoints, and so forth,
+even when it also displays the contents of those addresses. The default
+is on. For example, this is what a stack frame display looks like, with
+@code{set print address on}:
+
+@smallexample
+@group
+(@value{GDBP}) f
+#0 set_quotes (lq=0x34c78 "<<", rq=0x34c88 ">>")
+ at input.c:530
+530 if (lquote != def_lquote)
+@end group
+@end smallexample
+
+@item set print address off
+Do not print addresses when displaying their contents. For example,
+this is the same stack frame displayed with @code{set print address off}:
+
+@smallexample
+@group
+(@value{GDBP}) set print addr off
+(@value{GDBP}) f
+#0 set_quotes (lq="<<", rq=">>") at input.c:530
+530 if (lquote != def_lquote)
+@end group
+@end smallexample
+
+You can use @samp{set print address off} to eliminate all machine
+dependent displays from the @value{GDBN} interface. For example, with
+@code{print address off}, you should get the same text for backtraces on
+all machines---whether or not they involve pointer arguments.
+
+@item show print address
+@kindex show print address
+Show whether or not addresses are to be printed.
+@end table
+
+When @value{GDBN} prints a symbolic address, it normally prints the
+closest earlier symbol plus an offset. If that symbol does not uniquely
+identify the address (for example, it is a name whose scope is a single
+source file), you may need to disambiguate. One way to do this is with
+@code{info line}, for example @code{info line *0x4537}. Alternately,
+you can set @value{GDBN} to print the source file and line number when
+it prints a symbolic address:
+
+@table @code
+@item set print symbol-filename on
+@kindex set print symbol-filename
+Tell @value{GDBN} to print the source file name and line number of a
+symbol in the symbolic form of an address.
+
+@item set print symbol-filename off
+Do not print source file name and line number of a symbol. This is the
+default.
+
+@item show print symbol-filename
+@kindex show print symbol-filename
+Show whether or not @value{GDBN} will print the source file name and
+line number of a symbol in the symbolic form of an address.
+@end table
+
+Also, you may wish to see the symbolic form only if the address being
+printed is reasonably close to the closest earlier symbol:
+
+@table @code
+@item set print max-symbolic-offset @var{max-offset}
+@kindex set print max-symbolic-offset
+Tell @value{GDBN} to only display the symbolic form of an address if the
+offset between the closest earlier symbol and the address is less than
+@var{max-offset}. The default is 0, which means to always print the
+symbolic form of an address, if any symbol precedes it.
+
+@item show print max-symbolic-offset
+@kindex show print max-symbolic-offset
+Ask how large the maximum offset is that @value{GDBN} will print in a
+symbolic address.
+@end table
+
+@table @code
+@item set print array
+@itemx set print array on
+@kindex set print array
+@value{GDBN} will pretty-print arrays. This format is more convenient to read,
+but uses more space. The default is off.
+
+@item set print array off
+Return to compressed format for arrays.
+
+@item show print array
+@kindex show print array
+Show whether compressed or pretty format is selected for displaying
+arrays.
+
+@item set print elements @var{number-of-elements}
+@kindex set print elements
+If @value{GDBN} is printing a large array, it will stop printing after it has
+printed the number of elements set by the @code{set print elements} command.
+This limit also applies to the display of strings.
+Setting the number of elements to zero means that the printing is unlimited.
+
+@item show print elements
+@kindex show print elements
+Display the number of elements of a large array that @value{GDBN} will print
+before losing patience.
+
+@item set print pretty on
+@kindex set print pretty
+Cause @value{GDBN} to print structures in an indented format with one member per
+line, like this:
+
+@smallexample
+@group
+$1 = @{
+ next = 0x0,
+ flags = @{
+ sweet = 1,
+ sour = 1
+ @},
+ meat = 0x54 "Pork"
+@}
+@end group
+@end smallexample
+
+@item set print pretty off
+Cause @value{GDBN} to print structures in a compact format, like this:
+
+@smallexample
+@group
+$1 = @{next = 0x0, flags = @{sweet = 1, sour = 1@}, \
+meat = 0x54 "Pork"@}
+@end group
+@end smallexample
+
+@noindent
+This is the default format.
+
+@item show print pretty
+@kindex show print pretty
+Show which format @value{GDBN} will use to print structures.
+
+@item set print sevenbit-strings on
+@kindex set print sevenbit-strings
+Print using only seven-bit characters; if this option is set,
+@value{GDBN} will display any eight-bit characters (in strings or character
+values) using the notation @code{\}@var{nnn}. For example, @kbd{M-a} is
+displayed as @code{\341}.
+
+@item set print sevenbit-strings off
+Print using either seven-bit or eight-bit characters, as required. This
+is the default.
+
+@item show print sevenbit-strings
+@kindex show print sevenbit-strings
+Show whether or not @value{GDBN} will print only seven-bit characters.
+
+@item set print union on
+@kindex set print union
+Tell @value{GDBN} to print unions which are contained in structures. This is the
+default setting.
+
+@item set print union off
+Tell @value{GDBN} not to print unions which are contained in structures.
+
+@item show print union
+@kindex show print union
+Ask @value{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 @code{set print union on} in effect @samp{p foo} would print
+
+@smallexample
+$1 = @{it = Tree, form = @{tree = Acorn, bug = Cocoon@}@}
+@end smallexample
+
+@noindent
+and with @code{set print union off} in effect it would print
+
+@smallexample
+$1 = @{it = Tree, form = @{...@}@}
+@end smallexample
+@end table
+
+@ifclear CONLY
+@need 1000
+@noindent
+These settings are of interest when debugging C++ programs:
+
+@table @code
+@item set print demangle
+@itemx set print demangle on
+@kindex set print demangle
+Print C++ names in their source form rather than in the encoded
+(``mangled'') form passed to the assembler and linker for type-safe
+linkage. The default is @samp{on}.
+
+@item show print demangle
+@kindex show print demangle
+Show whether C++ names will be printed in mangled or demangled form.
+
+@item set print asm-demangle
+@itemx set print asm-demangle on
+@kindex set print 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 print asm-demangle
+@kindex show print asm-demangle
+Show whether C++ names in assembly listings will be printed in mangled
+or demangled form.
+
+@item set demangle-style @var{style}
+@kindex set demangle-style
+@cindex C++ symbol decoding style
+@cindex symbol decoding style, C++
+Choose among several encoding schemes used by different compilers to
+represent C++ names. The choices for @var{style} are currently:
+
+@table @code
+@item auto
+Allow @value{GDBN} to choose a decoding style by inspecting your program.
+
+@item gnu
+Decode based on the GNU C++ compiler (@code{g++}) encoding algorithm.
+
+@item lucid
+Decode based on the Lucid C++ compiler (@code{lcc}) encoding algorithm.
+
+@item arm
+Decode using the algorithm in the @cite{C++ Annotated Reference Manual}.
+@strong{Warning:} this setting alone is not sufficient to allow
+debugging @code{cfront}-generated executables. @value{GDBN} would
+require further enhancement to permit that.
+@end table
+
+@item show demangle-style
+@kindex show demangle-style
+Display the encoding style currently in use for decoding C++ symbols.
+
+@item set print object
+@itemx set print object on
+@kindex set print object
+When displaying a pointer to an object, identify the @emph{actual}
+(derived) type of the object rather than the @emph{declared} type, using
+the virtual function table.
+
+@item set print object off
+Display only the declared type of objects, without reference to the
+virtual function table. This is the default setting.
+
+@item show print object
+@kindex show print object
+Show whether actual, or declared, object types will be displayed.
+
+@item set print vtbl
+@itemx set print vtbl on
+@kindex set print vtbl
+Pretty print C++ virtual function tables. The default is off.
+
+@item set print vtbl off
+Do not pretty print C++ virtual function tables.
+
+@item show print vtbl
+@kindex show print vtbl
+Show whether C++ virtual function tables are pretty printed, or not.
+@end table
+@end ifclear
+
+@node Value History
+@section Value history
+
+@cindex value history
+Values printed by the @code{print} command are saved in the @value{GDBN} @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 @code{file} or @code{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} by which you can
+refer to them. These are successive integers starting with one.
+@code{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 way @code{print} labels its output 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 @code{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 @code{print} command
+remains 4 even though the value of @code{x} has changed.
+
+@table @code
+@kindex show values
+@item show values
+Print the last ten values in the value history, with their item numbers.
+This is like @samp{p@ $$9} repeated ten times, except that @code{show
+values} does not change the history.
+
+@item show values @var{n}
+Print ten history values centered on history item number @var{n}.
+
+@item show values +
+Print ten history values just after the values last printed. If no more
+values are available, produces no display.
+@end table
+
+Pressing @key{RET} to repeat @code{show values @var{n}} has exactly the
+same effect as @samp{show values +}.
+
+@node Convenience Vars
+@section Convenience variables
+
+@cindex convenience variables
+@value{GDBN} provides @dfn{convenience variables} that you can use within
+@value{GDBN} to hold on to a value and refer to it later. These variables
+exist entirely within @value{GDBN}; they are not part of your program, and
+setting a convenience variable has no direct effect on further execution
+of your program. That is why you can use them freely.
+
+Convenience variables are prefixed with @samp{$}. Any name preceded by
+@samp{$} can be used for a convenience variable, unless it is one of
+the predefined machine-specific register names (@pxref{Registers}).
+(Value history references, in contrast, are @emph{numbers} preceded
+by @samp{$}. @xref{Value History, ,Value history}.)
+
+You can save a value in a convenience variable with an assignment
+expression, just as you would set a variable in your program.
+For 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 show convenience
+@kindex show convenience
+Print a list of convenience variables used so far, and their values.
+Abbreviated @code{show 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:
+
+@example
+set $i = 0
+print bar[$i++]->contents
+@i{@dots{} repeat that command by typing @key{RET}.}
+@end example
+
+Some convenience variables are created automatically by @value{GDBN} and given
+values likely to be useful.
+
+@table @code
+@item $_
+@kindex $_
+The variable @code{$_} is automatically set by the @code{x} command to
+the last address examined (@pxref{Memory, ,Examining memory}). Other
+commands which provide a default address for @code{x} to examine also
+set @code{$_} to that address; these commands include @code{info line}
+and @code{info breakpoint}. The type of @code{$_} is @code{void *}
+except when set by the @code{x} command, in which case it is a pointer
+to the type of @code{$__}.
+
+@item $__
+@kindex $__
+The variable @code{$__} is automatically set by the @code{x} command
+to the value found in the last address examined. Its type is chosen
+to match the format in which the data was printed.
+@end table
+
+@node Registers
+@section Registers
+
+@cindex registers
+You can refer to machine register contents, in expressions, as variables
+with names starting with @samp{$}. The names of registers are different
+for each machine; use @code{info registers} to see the names used on
+your machine.
+
+@table @code
+@item info registers
+@kindex info registers
+Print the names and values of all registers except floating-point
+registers (in the selected stack frame).
+
+@item info all-registers
+@kindex info all-registers
+@cindex floating point registers
+Print the names and values of all registers, including floating-point
+registers.
+
+@item info registers @var{regname} @dots{}
+Print the relativized value of each specified 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
+
+@value{GDBN} has four ``standard'' register names that are available (in
+expressions) on most machines---whenever they do not conflict with an
+architecture's canonical mnemonics for registers. The register names
+@code{$pc} and @code{$sp} are used for the program counter register and
+the stack pointer. @code{$fp} is used for a register that contains a
+pointer to the current stack frame, and @code{$ps} is used for a
+register that contains the processor status. 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@footnote{This 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 @code{return};
+@pxref{Returning, ,Returning from a function}.} with
+
+@example
+set $sp += 4
+@end example
+
+Whenever possible, these four standard register names are available on
+your machine even though the machine has different canonical mnemonics,
+so long as there is no conflict. The @code{info registers} command
+shows the canonical 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}.
+
+@value{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, @value{GDBN} normally works with the virtual format only (the format that
+makes sense for your program), but the @code{info registers} command
+prints the data in both formats.
+
+Normally, register values are relative to the selected stack frame
+(@pxref{Selection, ,Selecting a frame}). 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
+true contents of hardware registers, you must select the innermost
+frame (with @samp{frame 0}).
+
+However, @value{GDBN} must deduce where registers are saved, from the machine
+code generated by your compiler. If some registers are not saved, or if
+@value{GDBN} is unable to locate the saved registers, the selected stack
+frame will make no difference.
+
+@ifset AMD29K
+@table @code
+@item set rstack_high_address @var{address}
+@kindex set rstack_high_address
+@cindex AMD 29K register stack
+@cindex register stack, AMD29K
+On AMD 29000 family processors, registers are saved in a separate
+``register stack''. There is no way for @value{GDBN} to determine the extent
+of this stack. Normally, @value{GDBN} just assumes that the stack is ``large
+enough''. This may result in @value{GDBN} referencing memory locations that
+do not exist. If necessary, you can get around this problem by
+specifying the ending address of the register stack with the @code{set
+rstack_high_address} command. The argument should be an address, which
+you will probably want to precede with @samp{0x} to specify in
+hexadecimal.
+
+@item show rstack_high_address
+@kindex show rstack_high_address
+Display the current limit of the register stack, on AMD 29000 family
+processors.
+@end table
+@end ifset
+
+@ifclear HAVE-FLOAT
+@node Floating Point Hardware
+@section Floating point hardware
+@cindex floating point
+
+@c FIXME! Really host, not target?
+Depending on the host machine architecture, @value{GDBN} may be able to give
+you more information about the status of the floating point hardware.
+
+@table @code
+@item info float
+@kindex info float
+Display hardware-dependent information about the floating
+point unit. The exact contents and layout vary depending on the
+floating point chip; on some platforms, @samp{info float} is not
+available at all.
+@end table
+@c FIXME: this is a cop-out. Try to get examples, explanations. Only
+@c FIXME...supported currently on arm's and 386's. Mark properly with
+@c FIXME... m4 macros to isolate general statements from hardware-dep,
+@c FIXME... at that point.
+@end ifclear
+
+@ifclear CONLY
+@node Languages
+@chapter Using @value{GDBN} with Different Languages
+@cindex languages
+
+@ifset MOD2
+Although programming languages generally have common aspects, they are
+rarely expressed in the same manner. For instance, in ANSI C,
+dereferencing a pointer @code{p} is accomplished by @code{*p}, but in
+Modula-2, it is accomplished by @code{p^}. Values can also be
+represented (and displayed) differently. Hex numbers in C are written
+like @samp{0x1ae}, while in Modula-2 they appear as @samp{1AEH}.
+@end ifset
+
+@cindex working language
+Language-specific information is built into @value{GDBN} for some languages,
+allowing you to express operations like the above in your program's
+native language, and allowing @value{GDBN} to output values in a manner
+consistent with the syntax of your program's native language. The
+language you use to build expressions, called the @dfn{working
+language}, can be selected manually, or @value{GDBN} can set it
+automatically.
+
+@menu
+* Setting:: Switching between source languages
+* Show:: Displaying the language
+@ifset MOD2
+* Checks:: Type and range checks
+@end ifset
+
+* Support:: Supported languages
+@end menu
+
+@node Setting
+@section Switching between source languages
+
+There are two ways to control the working language---either have @value{GDBN}
+set it automatically, or select it manually yourself. You can use the
+@code{set language} command for either purpose. On startup, @value{GDBN}
+defaults to setting the language automatically.
+
+@menu
+* Manually:: Setting the working language manually
+* Automatically:: Having @value{GDBN} infer the source language
+@end menu
+
+@node Manually
+@subsection Setting the working language
+
+If you allow @value{GDBN} to set the language automatically,
+expressions are interpreted the same way in your debugging session and
+your program.
+
+@kindex set language
+If you wish, you may set the language manually. To do this, issue the
+command @samp{set language @var{lang}}, where @var{lang} is the name of
+a language, such as
+@ifclear MOD2
+@code{c}.
+@end ifclear
+@ifset MOD2
+@code{c} or @code{modula-2}.
+@end ifset
+For a list of the supported languages, type @samp{set language}.
+@c FIXME: rms: eventually this command should be "help set language".
+
+@ifset MOD2
+Setting the language manually prevents @value{GDBN} from updating the working
+language automatically. This can lead to confusion if you try
+to debug a program when the working language is not the same as the
+source language, when an expression is acceptable to both
+languages---but means different things. For instance, if the current
+source file were written in C, and @value{GDBN} was parsing Modula-2, a
+command such as:
+
+@example
+print a = b + c
+@end example
+
+@noindent
+might not have the effect you intended. In C, this means to add
+@code{b} and @code{c} and place the result in @code{a}. The result
+printed would be the value of @code{a}. In Modula-2, this means to compare
+@code{a} to the result of @code{b+c}, yielding a @code{BOOLEAN} value.
+@end ifset
+
+@node Automatically
+@subsection Having @value{GDBN} infer the source language
+
+To have @value{GDBN} set the working language automatically, use @samp{set
+language local} or @samp{set language auto}. @value{GDBN} then infers the
+language that a program was written in by looking at the name of its
+source files, and examining their extensions:
+
+@table @file
+@ifset MOD2
+@item *.mod
+Modula-2 source file
+@end ifset
+
+@item *.c
+C source file
+
+@item *.C
+@itemx *.cc
+C++ source file
+@end table
+
+This information is recorded for each function or procedure in a source
+file. When your program stops in a frame (usually by encountering a
+breakpoint), @value{GDBN} sets the working language to the language recorded
+for the function in that frame. If the language for a frame is unknown
+(that is, if the function or block corresponding to the frame was
+defined in a source file that does not have a recognized extension), the
+current working language is not changed, and @value{GDBN} issues a warning.
+
+This may not seem necessary for most programs, which are written
+entirely in one source language. However, program modules and libraries
+written in one source language can be used by a main program written in
+a different source language. Using @samp{set language auto} in this
+case frees you from having to set the working language manually.
+
+@node Show
+@section Displaying the language
+
+The following commands will help you find out which language is the
+working language, and also what language source files were written in.
+
+@kindex show language
+@kindex info frame
+@kindex info source
+@table @code
+@item show language
+Display the current working language. This is the
+language you can use with commands such as @code{print} to
+build and compute expressions that may involve variables in your program.
+
+@item info frame
+Among the other information listed here (@pxref{Frame Info, ,Information
+about a frame}) is the source language for this frame. This is the
+language that will become the working language if you ever use an
+identifier that is in this frame.
+
+@item info source
+Among the other information listed here (@pxref{Symbols, ,Examining the
+Symbol Table}) is the source language of this source file.
+@end table
+
+@ifset MOD2
+@node Checks
+@section Type and range checking
+
+@quotation
+@emph{Warning:} In this release, the @value{GDBN} commands for type and range
+checking are included, but they do not yet have any effect. This
+section documents the intended facilities.
+@end quotation
+@c FIXME remove warning when type/range code added
+
+Some languages are designed to guard you against making seemingly common
+errors through a series of compile- and run-time checks. These include
+checking the type of arguments to functions and operators, and making
+sure mathematical overflows are caught at run time. Checks such as
+these help to ensure a program's correctness once it has been compiled
+by eliminating type mismatches, and providing active checks for range
+errors when your program is running.
+
+@value{GDBN} can check for conditions like the above if you wish.
+Although @value{GDBN} will not check the statements in your program, it
+can check expressions entered directly into @value{GDBN} for evaluation via
+the @code{print} command, for example. As with the working language,
+@value{GDBN} can also decide whether or not to check automatically based on
+your program's source language. @xref{Support, ,Supported languages},
+for the default settings of supported languages.
+
+@menu
+* Type Checking:: An overview of type checking
+* Range Checking:: An overview of range checking
+@end menu
+
+@cindex type checking
+@cindex checks, type
+@node Type Checking
+@subsection An overview of type checking
+
+Some languages, such as Modula-2, are strongly typed, meaning that the
+arguments to operators and functions have to be of the correct type,
+otherwise an error occurs. These checks prevent type mismatch
+errors from ever causing any run-time problems. For example,
+
+@example
+1 + 2 @result{} 3
+@exdent but
+@error{} 1 + 2.3
+@end example
+
+The second example fails because the @code{CARDINAL} 1 is not
+type-compatible with the @code{REAL} 2.3.
+
+For expressions you use in @value{GDBN} commands, you can tell the @value{GDBN}
+type checker to skip checking; to treat any mismatches as errors and
+abandon the expression; or only issue warnings when type mismatches
+occur, but evaluate the expression anyway. When you choose the last of
+these, @value{GDBN} evaluates expressions like the second example above, but
+also issues a warning.
+
+Even though you may turn type checking off, other type-based reasons may
+prevent @value{GDBN} from evaluating an expression. For instance, @value{GDBN} does not
+know how to add an @code{int} and a @code{struct foo}. These particular
+type errors have nothing to do with the language in use, and usually
+arise from expressions, such as the one described above, which make
+little sense to evaluate anyway.
+
+Each language defines to what degree it is strict about type. For
+instance, both Modula-2 and C require the arguments to arithmetical
+operators to be numbers. In C, enumerated types and pointers can be
+represented as numbers, so that they are valid arguments to mathematical
+operators. @xref{Support, ,Supported languages}, for further
+details on specific languages.
+
+@value{GDBN} provides some additional commands for controlling the type checker:
+
+@kindex set check
+@kindex set check type
+@kindex show check type
+@table @code
+@item set check type auto
+Set type checking on or off based on the current working language.
+@xref{Support, ,Supported languages}, for the default settings for
+each language.
+
+@item set check type on
+@itemx set check type off
+Set type checking on or off, overriding the default setting for the
+current working language. Issue a warning if the setting does not
+match the language default. If any type mismatches occur in
+evaluating an expression while typechecking is on, @value{GDBN} prints a
+message and aborts evaluation of the expression.
+
+@item set check type warn
+Cause the type checker to issue warnings, but to always attempt to
+evaluate the expression. Evaluating the expression may still
+be impossible for other reasons. For example, @value{GDBN} cannot add
+numbers and structures.
+
+@item show type
+Show the current setting of the type checker, and whether or not @value{GDBN} is
+setting it automatically.
+@end table
+
+@cindex range checking
+@cindex checks, range
+@node Range Checking
+@subsection An overview of range checking
+
+In some languages (such as Modula-2), it is an error to exceed the
+bounds of a type; this is enforced with run-time checks. Such range
+checking is meant to ensure program correctness by making sure
+computations do not overflow, or indices on an array element access do
+not exceed the bounds of the array.
+
+For expressions you use in @value{GDBN} commands, you can tell
+@value{GDBN} to treat range errors in one of three ways: ignore them,
+always treat them as errors and abandon the expression, or issue
+warnings but evaluate the expression anyway.
+
+A range error can result from numerical overflow, from exceeding an
+array index bound, or when you type a constant that is not a member
+of any type. Some languages, however, do not treat overflows as an
+error. In many implementations of C, mathematical overflow causes the
+result to ``wrap around'' to lower values---for example, if @var{m} is
+the largest integer value, and @var{s} is the smallest, then
+
+@example
+@var{m} + 1 @result{} @var{s}
+@end example
+
+This, too, is specific to individual languages, and in some cases
+specific to individual compilers or machines. @xref{Support, ,
+Supported languages}, for further details on specific languages.
+
+@value{GDBN} provides some additional commands for controlling the range checker:
+
+@kindex set check
+@kindex set check range
+@kindex show check range
+@table @code
+@item set check range auto
+Set range checking on or off based on the current working language.
+@xref{Support, ,Supported languages}, for the default settings for
+each language.
+
+@item set check range on
+@itemx set check range off
+Set range checking on or off, overriding the default setting for the
+current working language. A warning is issued if the setting does not
+match the language default. If a range error occurs, then a message
+is printed and evaluation of the expression is aborted.
+
+@item set check range warn
+Output messages when the @value{GDBN} range checker detects a range error,
+but attempt to evaluate the expression anyway. Evaluating the
+expression may still be impossible for other reasons, such as accessing
+memory that the process does not own (a typical example from many Unix
+systems).
+
+@item show range
+Show the current setting of the range checker, and whether or not it is
+being set automatically by @value{GDBN}.
+@end table
+@end ifset
+
+@node Support
+@section Supported languages
+
+@ifset MOD2
+@value{GDBN} 4 supports C, C++, and Modula-2.
+@end ifset
+@ifclear MOD2
+@value{GDBN} 4 supports C, and C++.
+@end ifclear
+Some @value{GDBN} features may be used in expressions regardless of the
+language you use: the @value{GDBN} @code{@@} and @code{::} operators,
+and the @samp{@{type@}addr} construct (@pxref{Expressions,
+,Expressions}) can be used with the constructs of any supported
+language.
+
+The following sections detail to what degree each source language is
+supported by @value{GDBN}. These sections are not meant to be language
+tutorials or references, but serve only as a reference guide to what the
+@value{GDBN} expression parser will accept, and what input and output
+formats should look like for different languages. There are many good
+books written on each of these languages; please look to these for a
+language reference or tutorial.
+
+@ifset MOD2
+@menu
+* C:: C and C++
+* Modula-2:: Modula-2
+@end menu
+
+@node C
+@subsection C and C++
+@cindex C and C++
+@cindex expressions in C or C++
+
+Since C and C++ are so closely related, many features of @value{GDBN} apply
+to both languages. Whenever this is the case, we discuss both languages
+together.
+@end ifset
+@ifclear MOD2
+@c Cancel this below, under same condition, at end of this chapter!
+@raisesections
+@end ifclear
+
+@cindex C++
+@kindex g++
+@cindex GNU C++
+The C++ debugging facilities are jointly implemented by the GNU C++
+compiler and @value{GDBN}. Therefore, to debug your C++ code effectively,
+you must compile your C++ programs with the GNU C++ compiler,
+@code{g++}.
+@end ifclear
+@ifset CONLY
+@node C
+@chapter C Language Support
+@cindex C language
+@cindex expressions in C
+
+Information specific to the C language is built into @value{GDBN} so that you
+can use C expressions while degugging. This also permits @value{GDBN} to
+output values in a manner consistent with C conventions.
+
+@menu
+* C Operators:: C operators
+* C Constants:: C constants
+* Debugging C:: @value{GDBN} and C
+@end menu
+@end ifset
+@ifclear CONLY
+@menu
+* C Operators:: C and C++ operators
+* C Constants:: C and C++ constants
+* Cplus expressions:: C++ expressions
+* C Defaults:: Default settings for C and C++
+@ifset MOD2
+* C Checks:: C and C++ type and range checks
+@end ifset
+
+* Debugging C:: @value{GDBN} and C
+* Debugging C plus plus:: Special features for C++
+@end menu
+@end ifclear
+
+@ifclear CONLY
+@cindex C and C++ operators
+@node C Operators
+@subsubsection C and C++ operators
+@end ifclear
+@ifset CONLY
+@cindex C operators
+@node C Operators
+@section C operators
+@end ifset
+
+Operators must be defined on values of specific types. For instance,
+@code{+} is defined on numbers, but not on structures. Operators are
+often defined on groups of types.
+
+@ifclear CONLY
+For the purposes of C and C++, the following definitions hold:
+@end ifclear
+
+@itemize @bullet
+@item
+@emph{Integral types} include @code{int} with any of its storage-class
+specifiers; @code{char}; and @code{enum}.
+
+@item
+@emph{Floating-point types} include @code{float} and @code{double}.
+
+@item
+@emph{Pointer types} include all types defined as @code{(@var{type}
+*)}.
+
+@item
+@emph{Scalar types} include all of the above.
+@end itemize
+
+@noindent
+The following operators are supported. They are listed here
+in order of increasing precedence:
+
+@table @code
+@item ,
+The comma or sequencing operator. Expressions in a comma-separated list
+are evaluated from left to right, with the result of the entire
+expression being the last expression evaluated.
+
+@item =
+Assignment. The value of an assignment expression is the value
+assigned. Defined on scalar types.
+
+@item @var{op}=
+Used in an expression of the form @w{@code{@var{a} @var{op}= @var{b}}},
+and translated to @w{@code{@var{a} = @var{a op b}}}.
+@w{@code{@var{op}=}} and @code{=} have the same precendence.
+@var{op} is any one of the operators @code{|}, @code{^}, @code{&},
+@code{<<}, @code{>>}, @code{+}, @code{-}, @code{*}, @code{/}, @code{%}.
+
+@item ?:
+The ternary operator. @code{@var{a} ? @var{b} : @var{c}} can be thought
+of as: if @var{a} then @var{b} else @var{c}. @var{a} should be of an
+integral type.
+
+@item ||
+Logical @sc{or}. Defined on integral types.
+
+@item &&
+Logical @sc{and}. Defined on integral types.
+
+@item |
+Bitwise @sc{or}. Defined on integral types.
+
+@item ^
+Bitwise exclusive-@sc{or}. Defined on integral types.
+
+@item &
+Bitwise @sc{and}. Defined on integral types.
+
+@item ==@r{, }!=
+Equality and inequality. Defined on scalar types. The value of these
+expressions is 0 for false and non-zero for true.
+
+@item <@r{, }>@r{, }<=@r{, }>=
+Less than, greater than, less than or equal, greater than or equal.
+Defined on scalar types. The value of these expressions is 0 for false
+and non-zero for true.
+
+@item <<@r{, }>>
+left shift, and right shift. Defined on integral types.
+
+@item @@
+The @value{GDBN} ``artificial array'' operator (@pxref{Expressions, ,Expressions}).
+
+@item +@r{, }-
+Addition and subtraction. Defined on integral types, floating-point types and
+pointer types.
+
+@item *@r{, }/@r{, }%
+Multiplication, division, and modulus. Multiplication and division are
+defined on integral and floating-point types. Modulus is defined on
+integral types.
+
+@item ++@r{, }--
+Increment and decrement. When appearing before a variable, the
+operation is performed before the variable is used in an expression;
+when appearing after it, the variable's value is used before the
+operation takes place.
+
+@item *
+Pointer dereferencing. Defined on pointer types. Same precedence as
+@code{++}.
+
+@item &
+Address operator. Defined on variables. Same precedence as @code{++}.
+
+@ifclear CONLY
+For debugging C++, @value{GDBN} implements a use of @samp{&} beyond what is
+allowed in the C++ language itself: you can use @samp{&(&@var{ref})}
+(or, if you prefer, simply @samp{&&@var{ref}}) to examine the address
+where a C++ reference variable (declared with @samp{&@var{ref}}) is
+stored.
+@end ifclear
+
+@item -
+Negative. Defined on integral and floating-point types. Same
+precedence as @code{++}.
+
+@item !
+Logical negation. Defined on integral types. Same precedence as
+@code{++}.
+
+@item ~
+Bitwise complement operator. Defined on integral types. Same precedence as
+@code{++}.
+
+
+@item .@r{, }->
+Structure member, and pointer-to-structure member. For convenience,
+@value{GDBN} regards the two as equivalent, choosing whether to dereference a
+pointer based on the stored type information.
+Defined on @code{struct} and @code{union} data.
+
+@item []
+Array indexing. @code{@var{a}[@var{i}]} is defined as
+@code{*(@var{a}+@var{i})}. Same precedence as @code{->}.
+
+@item ()
+Function parameter list. Same precedence as @code{->}.
+
+@ifclear CONLY
+@item ::
+C++ scope resolution operator. Defined on
+@code{struct}, @code{union}, and @code{class} types.
+@end ifclear
+
+@item ::
+Doubled colons
+@ifclear CONLY
+also
+@end ifclear
+represent the @value{GDBN} scope operator (@pxref{Expressions,
+,Expressions}).
+@ifclear CONLY
+Same precedence as @code{::}, above.
+@end ifclear
+@end table
+
+@ifclear CONLY
+@cindex C and C++ constants
+@node C Constants
+@subsubsection C and C++ constants
+
+@value{GDBN} allows you to express the constants of C and C++ in the
+following ways:
+@end ifclear
+@ifset CONLY
+@cindex C constants
+@node C Constants
+@section C constants
+
+@value{GDBN} allows you to express the constants of C in the
+following ways:
+@end ifset
+
+@itemize @bullet
+@item
+Integer constants are a sequence of digits. Octal constants are
+specified by a leading @samp{0} (ie. zero), and hexadecimal constants by
+a leading @samp{0x} or @samp{0X}. Constants may also end with a letter
+@samp{l}, specifying that the constant should be treated as a
+@code{long} value.
+
+@item
+Floating point constants are a sequence of digits, followed by a decimal
+point, followed by a sequence of digits, and optionally followed by an
+exponent. An exponent is of the form:
+@samp{@w{e@r{[[}+@r{]|}-@r{]}@var{nnn}}}, where @var{nnn} is another
+sequence of digits. The @samp{+} is optional for positive exponents.
+
+@item
+Enumerated constants consist of enumerated identifiers, or their
+integral equivalents.
+
+@item
+Character constants are a single character surrounded by single quotes
+(@code{'}), or a number---the ordinal value of the corresponding character
+(usually its @sc{ASCII} value). Within quotes, the single character may
+be represented by a letter or by @dfn{escape sequences}, which are of
+the form @samp{\@var{nnn}}, where @var{nnn} is the octal representation
+of the character's ordinal value; or of the form @samp{\@var{x}}, where
+@samp{@var{x}} is a predefined special character---for example,
+@samp{\n} for newline.
+
+@item
+String constants are a sequence of character constants surrounded
+by double quotes (@code{"}).
+
+@item
+Pointer constants are an integral value. You can also write pointers
+to constants using the C operator @samp{&}.
+
+@item
+Array constants are comma-separated lists surrounded by braces @samp{@{}
+and @samp{@}}; for example, @samp{@{1,2,3@}} is a three-element array of
+integers, @samp{@{@{1,2@}, @{3,4@}, @{5,6@}@}} is a three-by-two array,
+and @samp{@{&"hi", &"there", &"fred"@}} is a three-element array of pointers.
+@end itemize
+
+@ifclear CONLY
+@node Cplus expressions
+@subsubsection C++ expressions
+
+@cindex expressions in C++
+@value{GDBN} expression handling has a number of extensions to
+interpret a significant subset of C++ expressions.
+
+@cindex C++ support, not in @sc{coff}
+@cindex @sc{coff} versus C++
+@cindex C++ and object formats
+@cindex object formats and C++
+@cindex a.out and C++
+@cindex @sc{ecoff} and C++
+@cindex @sc{xcoff} and C++
+@cindex @sc{elf}/stabs and C++
+@cindex @sc{elf}/@sc{dwarf} and C++
+@quotation
+@emph{Warning:} Most of these extensions depend on the use of additional
+debugging information in the symbol table, and thus require a rich,
+extendable object code format. In particular, if your system uses
+a.out, MIPS @sc{ecoff}, RS/6000 @sc{xcoff}, or Sun @sc{elf} with stabs
+extensions to the symbol table, these facilities are all available.
+Where the object code format is standard @sc{coff}, on the other hand,
+most of the C++ support in @value{GDBN} will @emph{not} work, nor can it.
+For the standard SVr4 debugging format, @sc{dwarf} in @sc{elf}, the
+standard is still evolving, so the C++ support in @value{GDBN} is still
+fragile; when this debugging format stabilizes, however, C++ support
+will also be available on systems that use it.
+@end quotation
+
+@enumerate
+
+@cindex member functions
+@item
+Member function calls are allowed; you can use expressions like
+
+@example
+count = aml->GetOriginal(x, y)
+@end example
+
+@kindex this
+@cindex namespace in C++
+@item
+While a member function is active (in the selected stack frame), your
+expressions have the same namespace available as the member function;
+that is, @value{GDBN} allows implicit references to the class instance
+pointer @code{this} following the same rules as C++.
+
+@cindex call overloaded functions
+@cindex type conversions in C++
+@item
+You can call overloaded functions; @value{GDBN} will resolve the function
+call to the right definition, with one restriction---you must use
+arguments of the type required by the function that you want to call.
+@value{GDBN} will not perform conversions requiring constructors or
+user-defined type operators.
+
+@cindex reference declarations
+@item
+@value{GDBN} understands variables declared as C++ references; you can use them in
+expressions just as you do in C++ source---they are automatically
+dereferenced.
+
+In the parameter list shown when @value{GDBN} displays a frame, the values of
+reference variables are not displayed (unlike other variables); this
+avoids clutter, since references are often used for large structures.
+The @emph{address} of a reference variable is always shown, unless
+you have specified @samp{set print address off}.
+
+@item
+@value{GDBN} supports the C++ name resolution operator @code{::}---your
+expressions can use it just as expressions in your program do. Since
+one scope may be defined in another, you can use @code{::} repeatedly if
+necessary, for example in an expression like
+@samp{@var{scope1}::@var{scope2}::@var{name}}. @value{GDBN} also allows
+resolving name scope by reference to source files, in both C and C++
+debugging (@pxref{Variables, ,Program variables}).
+@end enumerate
+
+@node C Defaults
+@subsubsection C and C++ defaults
+@cindex C and C++ defaults
+
+If you allow @value{GDBN} to set type and range checking automatically, they
+both default to @code{off} whenever the working language changes to
+C or C++. This happens regardless of whether you, or @value{GDBN},
+selected the working language.
+
+If you allow @value{GDBN} to set the language automatically, it sets the
+working language to C or C++ on entering code compiled from a source file
+whose name ends with @file{.c}, @file{.C}, or @file{.cc}.
+@xref{Automatically, ,Having @value{GDBN} infer the source language}, for
+further details.
+
+@ifset MOD2
+@c Type checking is (a) primarily motivated by Modula-2, and (b)
+@c unimplemented. If (b) changes, it might make sense to let this node
+@c appear even if Mod-2 does not, but meanwhile ignore it. pesch 16jul93.
+@node C Checks
+@subsubsection C and C++ type and range checks
+@cindex C and C++ checks
+
+By default, when @value{GDBN} parses C or C++ expressions, type checking
+is not used. However, if you turn type checking on, @value{GDBN} will
+consider two variables type equivalent if:
+
+@itemize @bullet
+@item
+The two variables are structured and have the same structure, union, or
+enumerated tag.
+
+@item
+Two two variables have the same type name, or types that have been
+declared equivalent through @code{typedef}.
+
+@ignore
+@c leaving this out because neither J Gilmore nor R Pesch understand it.
+@c FIXME--beers?
+@item
+The two @code{struct}, @code{union}, or @code{enum} variables are
+declared in the same declaration. (Note: this may not be true for all C
+compilers.)
+@end ignore
+@end itemize
+
+Range checking, if turned on, is done on mathematical operations. Array
+indices are not checked, since they are often used to index a pointer
+that is not itself an array.
+@end ifset
+@end ifclear
+
+@ifclear CONLY
+@node Debugging C
+@subsubsection @value{GDBN} and C
+@end ifclear
+@ifset CONLY
+@node Debugging C
+@section @value{GDBN} and C
+@end ifset
+
+The @code{set print union} and @code{show print union} commands apply to
+the @code{union} type. When set to @samp{on}, any @code{union} that is
+inside a @code{struct}
+@ifclear CONLY
+or @code{class}
+@end ifclear
+will also be printed.
+Otherwise, it will appear as @samp{@{...@}}.
+
+The @code{@@} operator aids in the debugging of dynamic arrays, formed
+with pointers and a memory allocation function. @xref{Expressions,
+,Expressions}.
+
+@ifclear CONLY
+@node Debugging C plus plus
+@subsubsection @value{GDBN} features for C++
+
+@cindex commands for C++
+Some @value{GDBN} commands are particularly useful with C++, and some are
+designed specifically for use with C++. Here is a summary:
+
+@table @code
+@cindex break in overloaded functions
+@item @r{breakpoint menus}
+When you want a breakpoint in a function whose name is overloaded,
+@value{GDBN} breakpoint menus help you specify which function definition
+you want. @xref{Breakpoint Menus,,Breakpoint menus}.
+
+@cindex overloading in C++
+@item rbreak @var{regex}
+Setting breakpoints using regular expressions is helpful for setting
+breakpoints on overloaded functions that are not members of any special
+classes.
+@xref{Set Breaks, ,Setting breakpoints}.
+
+@cindex C++ exception handling
+@item catch @var{exceptions}
+@itemx info catch
+Debug C++ exception handling using these commands. @xref{Exception
+Handling, ,Breakpoints and exceptions}.
+
+@cindex inheritance
+@item ptype @var{typename}
+Print inheritance relationships as well as other information for type
+@var{typename}.
+@xref{Symbols, ,Examining the Symbol Table}.
+
+@cindex C++ symbol display
+@item set print demangle
+@itemx show print demangle
+@itemx set print asm-demangle
+@itemx show print asm-demangle
+Control whether C++ symbols display in their source form, both when
+displaying code as C++ source and when displaying disassemblies.
+@xref{Print Settings, ,Print settings}.
+
+@item set print object
+@itemx show print object
+Choose whether to print derived (actual) or declared types of objects.
+@xref{Print Settings, ,Print settings}.
+
+@item set print vtbl
+@itemx show print vtbl
+Control the format for printing virtual function tables.
+@xref{Print Settings, ,Print settings}.
+
+@item @r{Overloaded symbol names}
+You can specify a particular definition of an overloaded symbol, using
+the same notation that is used to declare such symbols in C++: type
+@code{@var{symbol}(@var{types})} rather than just @var{symbol}. You can
+also use the @value{GDBN} command-line word completion facilities to list the
+available choices, or to finish the type list for you.
+@xref{Completion,, Command completion}, for details on how to do this.
+@end table
+@ifclear MOD2
+@c cancels "raisesections" under same conditions near bgn of chapter
+@lowersections
+@end ifclear
+
+@ifset MOD2
+@node Modula-2
+@subsection Modula-2
+@cindex Modula-2
+
+The extensions made to @value{GDBN} to support Modula-2 only support
+output from the GNU Modula-2 compiler (which is currently being
+developed). Other Modula-2 compilers are not currently supported, and
+attempting to debug executables produced by them will most likely
+result in an error as @value{GDBN} reads in the executable's symbol
+table.
+
+@cindex expressions in Modula-2
+@menu
+* M2 Operators:: Built-in operators
+* Built-In Func/Proc:: Built-in functions and procedures
+* M2 Constants:: Modula-2 constants
+* M2 Defaults:: Default settings for Modula-2
+* Deviations:: Deviations from standard Modula-2
+* M2 Checks:: Modula-2 type and range checks
+* M2 Scope:: The scope operators @code{::} and @code{.}
+* GDB/M2:: @value{GDBN} and Modula-2
+@end menu
+
+@node M2 Operators
+@subsubsection Operators
+@cindex Modula-2 operators
+
+Operators must be defined on values of specific types. For instance,
+@code{+} is defined on numbers, but not on structures. Operators are
+often defined on groups of types. For the purposes of Modula-2, the
+following definitions hold:
+
+@itemize @bullet
+
+@item
+@emph{Integral types} consist of @code{INTEGER}, @code{CARDINAL}, and
+their subranges.
+
+@item
+@emph{Character types} consist of @code{CHAR} and its subranges.
+
+@item
+@emph{Floating-point types} consist of @code{REAL}.
+
+@item
+@emph{Pointer types} consist of anything declared as @code{POINTER TO
+@var{type}}.
+
+@item
+@emph{Scalar types} consist of all of the above.
+
+@item
+@emph{Set types} consist of @code{SET} and @code{BITSET} types.
+
+@item
+@emph{Boolean types} consist of @code{BOOLEAN}.
+@end itemize
+
+@noindent
+The following operators are supported, and appear in order of
+increasing precedence:
+
+@table @code
+@item ,
+Function argument or array index separator.
+
+@item :=
+Assignment. The value of @var{var} @code{:=} @var{value} is
+@var{value}.
+
+@item <@r{, }>
+Less than, greater than on integral, floating-point, or enumerated
+types.
+
+@item <=@r{, }>=
+Less than, greater than, less than or equal to, greater than or equal to
+on integral, floating-point and enumerated types, or set inclusion on
+set types. Same precedence as @code{<}.
+
+@item =@r{, }<>@r{, }#
+Equality and two ways of expressing inequality, valid on scalar types.
+Same precedence as @code{<}. In @value{GDBN} scripts, only @code{<>} is
+available for inequality, since @code{#} conflicts with the script
+comment character.
+
+@item IN
+Set membership. Defined on set types and the types of their members.
+Same precedence as @code{<}.
+
+@item OR
+Boolean disjunction. Defined on boolean types.
+
+@item AND@r{, }&
+Boolean conjuction. Defined on boolean types.
+
+@item @@
+The @value{GDBN} ``artificial array'' operator (@pxref{Expressions, ,Expressions}).
+
+@item +@r{, }-
+Addition and subtraction on integral and floating-point types, or union
+and difference on set types.
+
+@item *
+Multiplication on integral and floating-point types, or set intersection
+on set types.
+
+@item /
+Division on floating-point types, or symmetric set difference on set
+types. Same precedence as @code{*}.
+
+@item DIV@r{, }MOD
+Integer division and remainder. Defined on integral types. Same
+precedence as @code{*}.
+
+@item -
+Negative. Defined on @code{INTEGER} and @code{REAL} data.
+
+@item ^
+Pointer dereferencing. Defined on pointer types.
+
+@item NOT
+Boolean negation. Defined on boolean types. Same precedence as
+@code{^}.
+
+@item .
+@code{RECORD} field selector. Defined on @code{RECORD} data. Same
+precedence as @code{^}.
+
+@item []
+Array indexing. Defined on @code{ARRAY} data. Same precedence as @code{^}.
+
+@item ()
+Procedure argument list. Defined on @code{PROCEDURE} objects. Same precedence
+as @code{^}.
+
+@item ::@r{, }.
+@value{GDBN} and Modula-2 scope operators.
+@end table
+
+@quotation
+@emph{Warning:} Sets and their operations are not yet supported, so @value{GDBN}
+will treat the use of the operator @code{IN}, or the use of operators
+@code{+}, @code{-}, @code{*}, @code{/}, @code{=}, , @code{<>}, @code{#},
+@code{<=}, and @code{>=} on sets as an error.
+@end quotation
+
+@cindex Modula-2 built-ins
+@node Built-In Func/Proc
+@subsubsection Built-in functions and procedures
+
+Modula-2 also makes available several built-in procedures and functions.
+In describing these, the following metavariables are used:
+
+@table @var
+
+@item a
+represents an @code{ARRAY} variable.
+
+@item c
+represents a @code{CHAR} constant or variable.
+
+@item i
+represents a variable or constant of integral type.
+
+@item m
+represents an identifier that belongs to a set. Generally used in the
+same function with the metavariable @var{s}. The type of @var{s} should
+be @code{SET OF @var{mtype}} (where @var{mtype} is the type of @var{m}).
+
+@item n
+represents a variable or constant of integral or floating-point type.
+
+@item r
+represents a variable or constant of floating-point type.
+
+@item t
+represents a type.
+
+@item v
+represents a variable.
+
+@item x
+represents a variable or constant of one of many types. See the
+explanation of the function for details.
+@end table
+
+All Modula-2 built-in procedures also return a result, described below.
+
+@table @code
+@item ABS(@var{n})
+Returns the absolute value of @var{n}.
+
+@item CAP(@var{c})
+If @var{c} is a lower case letter, it returns its upper case
+equivalent, otherwise it returns its argument
+
+@item CHR(@var{i})
+Returns the character whose ordinal value is @var{i}.
+
+@item DEC(@var{v})
+Decrements the value in the variable @var{v}. Returns the new value.
+
+@item DEC(@var{v},@var{i})
+Decrements the value in the variable @var{v} by @var{i}. Returns the
+new value.
+
+@item EXCL(@var{m},@var{s})
+Removes the element @var{m} from the set @var{s}. Returns the new
+set.
+
+@item FLOAT(@var{i})
+Returns the floating point equivalent of the integer @var{i}.
+
+@item HIGH(@var{a})
+Returns the index of the last member of @var{a}.
+
+@item INC(@var{v})
+Increments the value in the variable @var{v}. Returns the new value.
+
+@item INC(@var{v},@var{i})
+Increments the value in the variable @var{v} by @var{i}. Returns the
+new value.
+
+@item INCL(@var{m},@var{s})
+Adds the element @var{m} to the set @var{s} if it is not already
+there. Returns the new set.
+
+@item MAX(@var{t})
+Returns the maximum value of the type @var{t}.
+
+@item MIN(@var{t})
+Returns the minimum value of the type @var{t}.
+
+@item ODD(@var{i})
+Returns boolean TRUE if @var{i} is an odd number.
+
+@item ORD(@var{x})
+Returns the ordinal value of its argument. For example, the ordinal
+value of a character is its ASCII value (on machines supporting the
+ASCII character set). @var{x} must be of an ordered type, which include
+integral, character and enumerated types.
+
+@item SIZE(@var{x})
+Returns the size of its argument. @var{x} can be a variable or a type.
+
+@item TRUNC(@var{r})
+Returns the integral part of @var{r}.
+
+@item VAL(@var{t},@var{i})
+Returns the member of the type @var{t} whose ordinal value is @var{i}.
+@end table
+
+@quotation
+@emph{Warning:} Sets and their operations are not yet supported, so
+@value{GDBN} will treat the use of procedures @code{INCL} and @code{EXCL} as
+an error.
+@end quotation
+
+@cindex Modula-2 constants
+@node M2 Constants
+@subsubsection Constants
+
+@value{GDBN} allows you to express the constants of Modula-2 in the following
+ways:
+
+@itemize @bullet
+
+@item
+Integer constants are simply a sequence of digits. When used in an
+expression, a constant is interpreted to be type-compatible with the
+rest of the expression. Hexadecimal integers are specified by a
+trailing @samp{H}, and octal integers by a trailing @samp{B}.
+
+@item
+Floating point constants appear as a sequence of digits, followed by a
+decimal point and another sequence of digits. An optional exponent can
+then be specified, in the form @samp{E@r{[}+@r{|}-@r{]}@var{nnn}}, where
+@samp{@r{[}+@r{|}-@r{]}@var{nnn}} is the desired exponent. All of the
+digits of the floating point constant must be valid decimal (base 10)
+digits.
+
+@item
+Character constants consist of a single character enclosed by a pair of
+like quotes, either single (@code{'}) or double (@code{"}). They may
+also be expressed by their ordinal value (their ASCII value, usually)
+followed by a @samp{C}.
+
+@item
+String constants consist of a sequence of characters enclosed by a
+pair of like quotes, either single (@code{'}) or double (@code{"}).
+Escape sequences in the style of C are also allowed. @xref{C
+Constants, ,C and C++ constants}, for a brief explanation of escape
+sequences.
+
+@item
+Enumerated constants consist of an enumerated identifier.
+
+@item
+Boolean constants consist of the identifiers @code{TRUE} and
+@code{FALSE}.
+
+@item
+Pointer constants consist of integral values only.
+
+@item
+Set constants are not yet supported.
+@end itemize
+
+@node M2 Defaults
+@subsubsection Modula-2 defaults
+@cindex Modula-2 defaults
+
+If type and range checking are set automatically by @value{GDBN}, they
+both default to @code{on} whenever the working language changes to
+Modula-2. This happens regardless of whether you, or @value{GDBN},
+selected the working language.
+
+If you allow @value{GDBN} to set the language automatically, then entering
+code compiled from a file whose name ends with @file{.mod} will set the
+working language to Modula-2. @xref{Automatically, ,Having @value{GDBN} set
+the language automatically}, for further details.
+
+@node Deviations
+@subsubsection Deviations from standard Modula-2
+@cindex Modula-2, deviations from
+
+A few changes have been made to make Modula-2 programs easier to debug.
+This is done primarily via loosening its type strictness:
+
+@itemize @bullet
+@item
+Unlike in standard Modula-2, pointer constants can be formed by
+integers. This allows you to modify pointer variables during
+debugging. (In standard Modula-2, the actual address contained in a
+pointer variable is hidden from you; it can only be modified
+through direct assignment to another pointer variable or expression that
+returned a pointer.)
+
+@item
+C escape sequences can be used in strings and characters to represent
+non-printable characters. @value{GDBN} will print out strings with these
+escape sequences embedded. Single non-printable characters are
+printed using the @samp{CHR(@var{nnn})} format.
+
+@item
+The assignment operator (@code{:=}) returns the value of its right-hand
+argument.
+
+@item
+All built-in procedures both modify @emph{and} return their argument.
+@end itemize
+
+@node M2 Checks
+@subsubsection Modula-2 type and range checks
+@cindex Modula-2 checks
+
+@quotation
+@emph{Warning:} in this release, @value{GDBN} does not yet perform type or
+range checking.
+@end quotation
+@c FIXME remove warning when type/range checks added
+
+@value{GDBN} considers two Modula-2 variables type equivalent if:
+
+@itemize @bullet
+@item
+They are of types that have been declared equivalent via a @code{TYPE
+@var{t1} = @var{t2}} statement
+
+@item
+They have been declared on the same line. (Note: This is true of the
+GNU Modula-2 compiler, but it may not be true of other compilers.)
+@end itemize
+
+As long as type checking is enabled, any attempt to combine variables
+whose types are not equivalent is an error.
+
+Range checking is done on all mathematical operations, assignment, array
+index bounds, and all built-in functions and procedures.
+
+@node M2 Scope
+@subsubsection The scope operators @code{::} and @code{.}
+@cindex scope
+@kindex .
+@cindex colon, doubled as scope operator
+@ifinfo
+@kindex colon-colon
+@c Info cannot handle :: but TeX can.
+@end ifinfo
+@iftex
+@kindex ::
+@end iftex
+
+There are a few subtle differences between the Modula-2 scope operator
+(@code{.}) and the @value{GDBN} scope operator (@code{::}). The two have
+similar syntax:
+
+@example
+
+@var{module} . @var{id}
+@var{scope} :: @var{id}
+@end example
+
+@noindent
+where @var{scope} is the name of a module or a procedure,
+@var{module} the name of a module, and @var{id} is any declared
+identifier within your program, except another module.
+
+Using the @code{::} operator makes @value{GDBN} search the scope
+specified by @var{scope} for the identifier @var{id}. If it is not
+found in the specified scope, then @value{GDBN} will search all scopes
+enclosing the one specified by @var{scope}.
+
+Using the @code{.} operator makes @value{GDBN} search the current scope for
+the identifier specified by @var{id} that was imported from the
+definition module specified by @var{module}. With this operator, it is
+an error if the identifier @var{id} was not imported from definition
+module @var{module}, or if @var{id} is not an identifier in
+@var{module}.
+
+@node GDB/M2
+@subsubsection @value{GDBN} and Modula-2
+
+Some @value{GDBN} commands have little use when debugging Modula-2 programs.
+Five subcommands of @code{set print} and @code{show print} apply
+specifically to C and C++: @samp{vtbl}, @samp{demangle},
+@samp{asm-demangle}, @samp{object}, and @samp{union}. The first four
+apply to C++, and the last to the C @code{union} type, which has no direct
+analogue in Modula-2.
+
+The @code{@@} operator (@pxref{Expressions, ,Expressions}), while available
+while using any language, is not useful with Modula-2. Its
+intent is to aid the debugging of @dfn{dynamic arrays}, which cannot be
+created in Modula-2 as they can in C or C++. However, because an
+address can be specified by an integral constant, the construct
+@samp{@{@var{type}@}@var{adrexp}} is still useful. (@pxref{Expressions, ,Expressions})
+
+@cindex @code{#} in Modula-2
+In @value{GDBN} scripts, the Modula-2 inequality operator @code{#} is
+interpreted as the beginning of a comment. Use @code{<>} instead.
+
+@end ifset
+@end ifclear
+
+@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 inherent in the text of your program and
+does not change as your program executes. @value{GDBN} finds it in your
+program's symbol table, in the file indicated when you started @value{GDBN}
+(@pxref{File Options, ,Choosing files}), or by one of the
+file-management commands (@pxref{Files, ,Commands to specify files}).
+
+@c FIXME! This might be intentionally specific to C and C++; if so, move
+@c to someplace in C section of lang chapter.
+@cindex symbol names
+@cindex names of symbols
+@cindex quoting names
+Occasionally, you may need to refer to symbols that contain unusual
+characters, which @value{GDBN} ordinarily treats as word delimiters. The
+most frequent case is in referring to static variables in other
+source files (@pxref{Variables,,Program variables}). File names
+are recorded in object files as debugging symbols, but @value{GDBN} would
+ordinarily parse a typical file name, like @file{foo.c}, as the three words
+@samp{foo} @samp{.} @samp{c}. To allow @value{GDBN} to recognize
+@samp{foo.c} as a single symbol, enclose it in single quotes; for example,
+
+@example
+p 'foo.c'::x
+@end example
+
+@noindent
+looks up the value of @code{x} in the scope of the file @file{foo.c}.
+
+@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 variable, 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, ,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
+@ifclear CONLY
+@samp{class @var{class-name}},
+@end ifclear
+@samp{struct @var{struct-tag}}, @samp{union @var{union-tag}} or
+@samp{enum @var{enum-tag}}.
+
+@item ptype @var{exp}
+@itemx ptype
+Print a description of the type of expression @var{exp}. @code{ptype}
+differs from @code{whatis} by printing a detailed description, instead
+of just the name of the type.
+
+For example, for this variable declaration:
+
+@example
+struct complex @{double real; double imag;@} v;
+@end example
+
+@noindent
+the two commands give this output:
+
+@example
+@group
+(@value{GDBP}) whatis v
+type = struct complex
+(@value{GDBP}) ptype v
+type = struct complex @{
+ double real;
+ double imag;
+@}
+@end group
+@end example
+
+@noindent
+As with @code{whatis}, using @code{ptype} without an argument refers to
+the type of @code{$}, the last value in the value history.
+
+@item info types @var{regexp}
+@itemx info types
+@kindex info types
+Print a brief description of all types whose name matches @var{regexp}
+(or all types in your program, if you supply no argument). Each
+complete typename is matched as though it were a complete line; thus,
+@samp{i type value} gives information on all types in your program whose
+name includes the string @code{value}, but @samp{i type ^value$} gives
+information only on types whose complete name is @code{value}.
+
+This command differs from @code{ptype} in two ways: first, like
+@code{whatis}, it does not print a detailed description; second, it
+lists all source files where a type is defined.
+
+@item info source
+@kindex info source
+Show the name of the current source file---that is, the source file for
+the function containing the current point of execution---and the language
+it was written in.
+
+@item info sources
+@kindex info sources
+Print the names of all source files in your program for which there is
+debugging information, organized into two lists: files whose symbols
+have already been read, and files whose symbols will be read when needed.
+
+@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 @code{step}; @samp{info fun ^step} finds those whose names
+start with @code{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 @code{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 @code{ptype} command can be overwhelming and hard to use. The
+@code{info-methods} command filters the methods, printing only those
+which match the regular-expression @var{regexp}.
+@end ignore
+
+@item maint print symbols @var{filename}
+@itemx maint print psymbols @var{filename}
+@itemx maint print msymbols @var{filename}
+@kindex maint print symbols
+@cindex symbol dump
+@kindex maint print psymbols
+@cindex partial symbol dump
+Write a dump of debugging symbol data into the file @var{filename}.
+These commands are used to debug the @value{GDBN} symbol-reading code. Only
+symbols with debugging data are included. If you use @samp{maint print
+symbols}, @value{GDBN} includes all the symbols for which it has already
+collected full details: that is, @var{filename} reflects symbols for
+only those files whose symbols @value{GDBN} has read. You can use the
+command @code{info sources} to find out which files these are. If you
+use @samp{maint print psymbols} instead, the dump shows information about
+symbols that @value{GDBN} only knows partially---that is, symbols defined in
+files that @value{GDBN} has skimmed, but not yet read completely. Finally,
+@samp{maint print msymbols} dumps just the minimal symbol information
+required for each object file from which @value{GDBN} has read some symbols.
+@xref{Files, ,Commands to specify files}, for a discussion of how
+@value{GDBN} reads symbols (in the description of @code{symbol-file}).
+@end table
+
+@node Altering
+@chapter Altering Execution
+
+Once you think you have found an error in your 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 @value{GDBN} features for altering execution of the
+program.
+
+For example, you can store new values into variables or memory
+locations,
+@ifclear BARETARGET
+give your program a signal, restart it
+@end ifclear
+@ifset BARETARGET
+restart your program
+@end ifset
+at a different address, or even return prematurely from a function to
+its caller.
+
+@menu
+* Assignment:: Assignment to variables
+* Jumping:: Continuing at a different address
+@ifclear BARETARGET
+* Signaling:: Giving your program a signal
+@end ifclear
+
+* Returning:: Returning from a function
+* Calling:: Calling your program's functions
+* Patching:: Patching your program
+@end menu
+
+@node Assignment
+@section Assignment to variables
+
+@cindex assignment
+@cindex setting variables
+To alter the value of a variable, evaluate an assignment expression.
+@xref{Expressions, ,Expressions}. For example,
+
+@example
+print x=4
+@end example
+
+@noindent
+stores the value 4 into the variable @code{x}, and then prints the
+value of the assignment expression (which is 4).
+@ifclear CONLY
+@xref{Languages, ,Using @value{GDBN} with Different Languages}, for more
+information on operators in supported languages.
+@end ifclear
+
+@kindex set variable
+@cindex variables, setting
+If you are not interested in seeing the value of the assignment, use the
+@code{set} command instead of the @code{print} command. @code{set} is
+really the same as @code{print} except that the expression's value is
+not printed and is not put in the value history (@pxref{Value History,
+,Value history}). The expression is evaluated only for its effects.
+
+If the beginning of the argument string of the @code{set} command
+appears identical to a @code{set} subcommand, use the @code{set
+variable} command instead of just @code{set}. This command is identical
+to @code{set} except for its lack of subcommands. For example, if
+your program has a variable @code{width}, you get
+an error if you try to set a new value with just @samp{set width=13},
+because @value{GDBN} has the command @code{set width}:
+
+@example
+(@value{GDBP}) whatis width
+type = double
+(@value{GDBP}) p width
+$4 = 13
+(@value{GDBP}) set width=47
+Invalid syntax in expression.
+@end example
+
+@noindent
+The invalid expression, of course, is @samp{=47}. In
+order to actually set the program's variable @code{width}, use
+
+@example
+(@value{GDBP}) set var width=47
+@end example
+
+@value{GDBN} allows more implicit conversions in assignments than C; you can
+freely store an integer value into a pointer variable or vice versa,
+and you can convert any structure 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, ,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 your program, you do so at the place where
+it stopped, with the @code{continue} command. You can instead continue at
+an address of your own choosing, with the following commands:
+
+@table @code
+@item jump @var{linespec}
+@kindex jump
+Resume execution at line @var{linespec}. Execution will stop
+immediately if there is a breakpoint there. @xref{List, ,Printing
+source lines}, for a description of the different forms of
+@var{linespec}.
+
+The @code{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{linespec} 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 @code{jump} command requests
+confirmation if the specified line is not in the function currently
+executing. However, even bizarre results are predictable if you are
+well acquainted with the machine-language code of your 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 your 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 @code{continue} command or stepping command to execute at
+address @code{0x485}, rather than at the address where your program stopped.
+@xref{Continuing and Stepping, ,Continuing and stepping}.
+
+The most common occasion to use the @code{jump} command is to back up,
+perhaps with more breakpoints set, over a portion of a program that has
+already executed, in order to examine its execution in more detail.
+
+@ifclear BARETARGET
+@c @group
+@node Signaling
+@section Giving your program a signal
+
+@table @code
+@item signal @var{signal}
+@kindex signal
+Resume execution where your program stopped, but immediately give it the
+signal @var{signal}. @var{signal} can be the name or the number of a
+signal. For example, on many systems @code{signal 2} and @code{signal
+SIGINT} are both ways of sending an interrupt signal.
+
+Alternatively, if @var{signal} is zero, continue execution without
+giving a signal. This is useful when your program stopped on account of
+a signal and would ordinary see the signal when resumed with the
+@code{continue} command; @samp{signal 0} causes it to resume without a
+signal.
+
+@code{signal} does not repeat when you press @key{RET} a second time
+after executing the command.
+@end table
+@c @end group
+
+Invoking the @code{signal} command is not the same as invoking the
+@code{kill} utility from the shell. Sending a signal with @code{kill}
+causes @value{GDBN} to decide what to do with the signal depending on
+the signal handling tables (@pxref{Signals}). The @code{signal} command
+passes the signal directly to your program.
+
+@end ifclear
+
+@node Returning
+@section Returning from a function
+
+@table @code
+@item return
+@itemx return @var{expression}
+@cindex returning from a function
+@kindex return
+You can cancel execution of a function call with the @code{return}
+command. If you give an
+@var{expression} argument, its value is used as the function's return
+value.
+@end table
+
+When you use @code{return}, @value{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, ,Selecting a
+frame}), 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 @code{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 @code{finish} command (@pxref{Continuing
+and Stepping, ,Continuing and stepping}) resumes execution until the
+selected stack frame returns naturally.
+
+@node Calling
+@section Calling program 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 @code{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 Patching
+@section Patching programs
+@cindex patching binaries
+@cindex writing into executables
+@ifclear BARETARGET
+@cindex writing into corefiles
+@end ifclear
+
+By default, @value{GDBN} opens the file containing your program's executable
+code
+@ifclear BARETARGET
+(or the corefile)
+@end ifclear
+read-only. This prevents accidental alterations
+to machine code; but it also prevents you from intentionally patching
+your program's binary.
+
+If you'd like to be able to patch the binary, you can specify that
+explicitly with the @code{set write} command. For example, you might
+want to turn on internal debugging flags, or even to make emergency
+repairs.
+
+@table @code
+@item set write on
+@itemx set write off
+@kindex set write
+If you specify @samp{set write on}, @value{GDBN} will open executable
+@ifclear BARETARGET
+and core
+@end ifclear
+files for both reading and writing; if you specify @samp{set write
+off} (the default), @value{GDBN} will open them read-only.
+
+If you have already loaded a file, you must load it again (using the
+@code{exec-file}
+@ifclear BARETARGET
+or @code{core-file}
+@end ifclear
+command) after changing @code{set write}, for your new setting to take
+effect.
+
+@item show write
+@kindex show write
+Display whether executable files
+@ifclear BARETARGET
+and core files
+@end ifclear
+will be opened for writing as well as reading.
+@end table
+
+@node GDB Files
+@chapter @value{GDBN} Files
+
+@value{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 your program.
+@ifclear BARETARGET
+To debug a core dump of a previous run, you must also tell @value{GDBN}
+the name of the core dump file.
+@end ifclear
+
+@menu
+* Files:: Commands to specify files
+* Symbol Errors:: Errors reading symbol files
+@end menu
+
+@node Files
+@section Commands to specify files
+@cindex symbol table
+
+@ifclear BARETARGET
+@cindex core dump file
+The usual way to specify executable and core dump file names is with
+the command arguments given when you start @value{GDBN} (@pxref{Invocation,
+,Getting In and Out of @value{GDBN}}.
+@end ifclear
+@ifset BARETARGET
+The usual way to specify an executable file name is with
+the command argument given when you start @value{GDBN}, (@pxref{Invocation,
+,Getting In and Out of @value{GDBN}}.
+@end ifset
+
+Occasionally it is necessary to change to a different file during a
+@value{GDBN} session. Or you may run @value{GDBN} and forget to specify
+a file you want to use. In these situations the @value{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 @code{run} command. If you do not specify a
+directory and the file is not found in the @value{GDBN} working directory, @value{GDBN}
+uses the environment variable @code{PATH} as a list of directories to
+search, just as the shell does when looking for a program to run. You
+can change the value of this variable, for both @value{GDBN} and your program,
+using the @code{path} command.
+
+On systems with memory-mapped files, an auxiliary symbol table file
+@file{@var{filename}.syms} may be available for @var{filename}. If it
+is, @value{GDBN} will map in the symbol table from
+@file{@var{filename}.syms}, starting up more quickly. See the
+descriptions of the options @samp{-mapped} and @samp{-readnow} (available
+on the command line, and with the commands @code{file}, @code{symbol-file},
+or @code{add-symbol-file}), for more information.
+
+@item file
+@code{file} with no argument makes @value{GDBN} discard any information it
+has on both executable file and the symbol table.
+
+@item exec-file @r{[} @var{filename} @r{]}
+@kindex exec-file
+Specify that the program to be run (but not the symbol table) is found
+in @var{filename}. @value{GDBN} will search the environment variable @code{PATH}
+if necessary to locate your program. Omitting @var{filename} means to
+discard information on the executable file.
+
+@item symbol-file @r{[} @var{filename} @r{]}
+@kindex symbol-file
+Read symbol table information from file @var{filename}. @code{PATH} is
+searched when necessary. Use the @code{file} command to get both symbol
+table and program to run from the same file.
+
+@code{symbol-file} with no argument clears out @value{GDBN} information on your
+program's symbol table.
+
+The @code{symbol-file} command causes @value{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 @value{GDBN}.
+
+@code{symbol-file} will not repeat if you press @key{RET} again after
+executing it once.
+
+When @value{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 a GNU compiler, or
+other compilers that adhere to the local conventions. Best results are
+usually obtained from GNU compilers; for example, using @code{@value{GCC}}
+you can generate debugging information for optimized code.
+
+On some kinds of object files, the @code{symbol-file} command does not
+normally 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,
+as they are needed.
+
+The purpose of this two-stage reading strategy is to make @value{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 @code{set verbose} command can turn these pauses
+into messages if desired. @xref{Messages/Warnings, ,Optional warnings
+and messages}.)
+
+We have not implemented the two-stage strategy for COFF yet. When the
+symbol table is stored in COFF format, @code{symbol-file} reads the
+symbol table data in full right away.
+
+@item symbol-file @var{filename} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+@itemx file @var{filename} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+@kindex readnow
+@cindex reading symbols immediately
+@cindex symbols, reading immediately
+@kindex mapped
+@cindex memory-mapped symbol file
+@cindex saving symbol table
+You can override the @value{GDBN} two-stage strategy for reading symbol
+tables by using the @samp{-readnow} option with any of the commands that
+load symbol table information, if you want to be sure @value{GDBN} has the
+entire symbol table available.
+
+@ifclear BARETARGET
+If memory-mapped files are available on your system through the
+@code{mmap} system call, you can use another option, @samp{-mapped}, to
+cause @value{GDBN} to write the symbols for your program into a reusable
+file. Future @value{GDBN} debugging sessions will map in symbol information
+from this auxiliary symbol file (if the program has not changed), rather
+than spending time reading the symbol table from the executable
+program. Using the @samp{-mapped} option has the same effect as
+starting @value{GDBN} with the @samp{-mapped} command-line option.
+
+You can use both options together, to make sure the auxiliary symbol
+file has all the symbol information for your program.
+
+The auxiliary symbol file for a program called @var{myprog} is called
+@samp{@var{myprog}.syms}. Once this file exists (so long as it is newer
+than the corresponding executable), @value{GDBN} will always attempt to use
+it when you debug @var{myprog}; no special options or commands are
+needed.
+
+The @file{.syms} file is specific to the host machine where you run
+@value{GDBN}. It holds an exact image of the internal @value{GDBN}
+symbol table. It cannot be shared across multiple host platforms.
+
+@c FIXME: for now no mention of directories, since this seems to be in
+@c flux. 13mar1992 status is that in theory GDB would look either in
+@c current dir or in same dir as myprog; but issues like competing
+@c GDB's, or clutter in system dirs, mean that in practice right now
+@c only current dir is used. FFish says maybe a special GDB hierarchy
+@c (eg rooted in val of env var GDBSYMS) could exist for mappable symbol
+@c files.
+
+@item core-file @r{[} @var{filename} @r{]}
+@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; @value{GDBN} can access the
+executable file itself for other parts.
+
+@code{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 @value{GDBN}. So, if you have been running your 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 @code{kill} command
+(@pxref{Kill Process, ,Killing the child process}).
+@end ifclear
+
+@item load @var{filename}
+@kindex load
+@ifset GENERIC
+Depending on what remote debugging facilities are configured into
+@value{GDBN}, the @code{load} command may be available. Where it exists, it
+is meant to make @var{filename} (an executable) available for debugging
+on the remote system---by downloading, or dynamic linking, for example.
+@code{load} also records the @var{filename} symbol table in @value{GDBN}, like
+the @code{add-symbol-file} command.
+
+If your @value{GDBN} does not have a @code{load} command, attempting to
+execute it gets the error message ``@code{You can't do that when your
+target is @dots{}}''
+@end ifset
+
+The file is loaded at whatever address is specified in the executable.
+For some object file formats, like a.out, the object file format fixes
+the address and so it won't necessarily match the address you gave to
+the linker.
+
+@ifset VXWORKS
+On VxWorks, @code{load} will dynamically link @var{filename} on the
+current target system as well as adding its symbols in @value{GDBN}.
+@end ifset
+
+@ifset I960
+@cindex download to Nindy-960
+With the Nindy interface to an Intel 960 board, @code{load} will
+download @var{filename} to the 960 as well as adding its symbols in
+@value{GDBN}.
+@end ifset
+
+@ifset H8
+@cindex download to H8/300 or H8/500
+@cindex H8/300 or H8/500 download
+@cindex download to Hitachi SH
+@cindex Hitachi SH download
+When you select remote debugging to a Hitachi SH, H8/300, or H8/500 board
+(@pxref{Hitachi Remote,,@value{GDBN} and Hitachi Microprocessors}),
+the @code{load} command downloads your program to the Hitachi board and also
+opens it as the current executable target for @value{GDBN} on your host
+(like the @code{file} command).
+@end ifset
+
+@code{load} will not repeat if you press @key{RET} again after using it.
+
+@ifclear BARETARGET
+@item add-symbol-file @var{filename} @var{address}
+@itemx add-symbol-file @var{filename} @var{address} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+@kindex add-symbol-file
+@cindex dynamic linking
+The @code{add-symbol-file} command reads additional symbol table information
+from the file @var{filename}. You would use this command when @var{filename}
+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; @value{GDBN} cannot figure this out for itself.
+You can specify @var{address} as an expression.
+
+The symbol table of the file @var{filename} is added to the symbol table
+originally read with the @code{symbol-file} command. You can use the
+@code{add-symbol-file} command any number of times; the new symbol data thus
+read keeps adding to the old. To discard all old symbol data instead,
+use the @code{symbol-file} command.
+
+@code{add-symbol-file} will not repeat if you press @key{RET} after using it.
+
+You can use the @samp{-mapped} and @samp{-readnow} options just as with
+the @code{symbol-file} command, to change how @value{GDBN} manages the symbol
+table information for @var{filename}.
+@end ifclear
+
+@item info files
+@itemx info target
+@kindex info files
+@kindex info target
+@code{info files} and @code{info target} are synonymous; both print
+the current target (@pxref{Targets, ,Specifying a Debugging Target}),
+including the
+@ifclear BARETARGET
+names of the executable and core dump files
+@end ifclear
+@ifset BARETARGET
+name of the executable file
+@end ifset
+currently in use by @value{GDBN}, and the files from which symbols were
+loaded. The command @code{help targets} lists all possible targets
+rather than current ones.
+@end table
+
+All file-specifying commands allow both absolute and relative file names
+as arguments. @value{GDBN} always converts the file name to an absolute path
+name and remembers it that way.
+
+@ifclear BARETARGET
+@cindex shared libraries
+@value{GDBN} supports SunOS, SVR4, and IBM RS/6000 shared libraries.
+@value{GDBN} automatically loads symbol definitions from shared libraries
+when you use the @code{run} command, or when you examine a core file.
+(Before you issue the @code{run} command, @value{GDBN} will not understand
+references to a function in a shared library, however---unless you are
+debugging a core file).
+@c FIXME: next @value{GDBN} release should permit some refs to undef
+@c FIXME...symbols---eg in a break cmd---assuming they are from a shared lib
+
+@table @code
+@item info share
+@itemx info sharedlibrary
+@kindex info sharedlibrary
+@kindex info share
+Print the names of the shared libraries which are currently loaded.
+
+@item sharedlibrary @var{regex}
+@itemx share @var{regex}
+@kindex sharedlibrary
+@kindex share
+This is an obsolescent command; you can use it to explicitly load shared
+object library symbols for files matching a Unix regular expression, but
+as with files loaded automatically, it will only load shared libraries
+required by your program for a core file or after typing @code{run}. If
+@var{regex} is omitted all shared libraries required by your program are
+loaded.
+@end table
+@end ifclear
+
+@node Symbol Errors
+@section Errors reading symbol files
+
+While reading a symbol file, @value{GDBN} will occasionally encounter problems,
+such as symbol types it does not recognize, or known bugs in compiler
+output. By default, @value{GDBN} does not notify you of such problems, since
+they are relatively common and primarily of interest to people
+debugging compilers. If you are interested in seeing information
+about ill-constructed symbol tables, you can either ask @value{GDBN} to print
+only one message about each such type of problem, no matter how many
+times the problem occurs; or you can ask @value{GDBN} to print more messages,
+to see how many times the problems occur, with the @code{set
+complaints} command (@pxref{Messages/Warnings, ,Optional warnings and
+messages}).
+
+The messages currently printed, and their meanings, include:
+
+@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.
+
+@value{GDBN} circumvents the problem by treating the inner block as if it had
+the same scope as the outer block. In the error message, @var{symbol}
+may be shown as ``@code{(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.
+
+@value{GDBN} does not circumvent this problem, and will have trouble
+locating symbols in the source file whose symbols it is reading. (You
+can often determine what source file is affected by specifying
+@code{set verbose on}. @xref{Messages/Warnings, ,Optional warnings and
+messages}.)
+
+@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.
+
+@value{GDBN} circumvents the problem by treating the symbol scope block as
+starting on the previous source line.
+
+@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.
+
+@value{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{0x@var{nn}}
+
+The symbol information contains new data types that @value{GDBN} does not yet
+know how to read. @code{0x@var{nn}} is the symbol type of the misunderstood
+information, in hexadecimal.
+
+@value{GDBN} circumvents the error by ignoring this symbol information. This
+will usually allow your 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 @code{@value{GDBP}} with itself, breakpoint on
+@code{complain}, then go up to the function @code{read_dbx_symtab} and
+examine @code{*bufp} to see the symbol.
+
+@item stub type has NULL name
+@value{GDBN} could not find the full definition for
+@ifclear CONLY
+a struct or class.
+@end ifclear
+@ifset CONLY
+a struct.
+@end ifset
+
+@ifclear CONLY
+@item const/volatile indicator missing (ok if using g++ v1.x), got@dots{}
+
+The symbol information for a C++ member function is missing some
+information that recent versions of the compiler should have output
+for it.
+@end ifclear
+
+@item info mismatch between compiler and debugger
+
+@value{GDBN} could not parse a type specification output by the compiler.
+@end table
+
+@node Targets
+@chapter Specifying a Debugging Target
+@cindex debugging target
+@kindex target
+
+A @dfn{target} is the execution environment occupied by your program.
+@ifclear BARETARGET
+Often, @value{GDBN} runs in the same host environment as your program; in
+that case, the debugging target is specified as a side effect when you
+use the @code{file} or @code{core} commands. When you need more
+flexibility---for example, running @value{GDBN} on a physically separate
+host, or controlling a standalone system over a serial port or a
+realtime system over a TCP/IP connection---you
+@end ifclear
+@ifset BARETARGET
+You
+@end ifset
+can use the @code{target} command to specify one of the target types
+configured for @value{GDBN} (@pxref{Target Commands, ,Commands for managing
+targets}).
+
+@menu
+* Active Targets:: Active targets
+* Target Commands:: Commands for managing targets
+* Remote:: Remote debugging
+@end menu
+
+@node Active Targets
+@section Active targets
+@cindex stacking targets
+@cindex active targets
+@cindex multiple targets
+
+@ifclear BARETARGET
+There are three classes of targets: processes, core files, and
+executable files. @value{GDBN} can work concurrently on up to three active
+targets, one in each class. This allows you to (for example) start a
+process and inspect its activity without abandoning your work on a core
+file.
+
+For example, if you execute @samp{gdb a.out}, then the executable file
+@code{a.out} is the only active target. If you designate a core file as
+well---presumably from a prior run that crashed and coredumped---then
+@value{GDBN} has two active targets and will use them in tandem, looking
+first in the corefile target, then in the executable file, to satisfy
+requests for memory addresses. (Typically, these two classes of target
+are complementary, since core files contain only a program's
+read-write memory---variables and so on---plus machine status, while
+executable files contain only the program text and initialized data.)
+@end ifclear
+
+When you type @code{run}, your executable file becomes an active process
+target as well. When a process target is active, all @value{GDBN} commands
+requesting memory addresses refer to that target; addresses in an
+@ifclear BARETARGET
+active core file or
+@end ifclear
+executable file target are obscured while the process
+target is active.
+
+@ifset BARETARGET
+Use the @code{exec-file} command to select a
+new executable target (@pxref{Files, ,Commands to specify
+files}).
+@end ifset
+@ifclear BARETARGET
+Use the @code{core-file} and @code{exec-file} commands to select a
+new core file or executable target (@pxref{Files, ,Commands to specify
+files}). To specify as a target a process that is already running, use
+the @code{attach} command (@pxref{Attach, ,Debugging an
+already-running process}).
+@end ifclear
+
+@node Target Commands
+@section Commands for managing targets
+
+@table @code
+@item target @var{type} @var{parameters}
+Connects the @value{GDBN} host environment to a target
+@ifset BARETARGET
+machine.
+@end ifset
+@ifclear BARETARGET
+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.
+
+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.
+@end ifclear
+
+The @code{target} command will not repeat if you press @key{RET} again
+after executing the command.
+
+@item help target
+@kindex help target
+Displays the names of all targets available. To display targets
+currently selected, use either @code{info target} or @code{info files}
+(@pxref{Files, ,Commands to specify files}).
+
+@item help target @var{name}
+Describe a particular target, including any parameters necessary to
+select it.
+@end table
+
+Here are some common targets (available, or not, depending on the GDB
+configuration):
+
+@table @code
+@item target exec @var{program}
+@kindex target exec
+An executable file. @samp{target exec @var{program}} is the same as
+@samp{exec-file @var{program}}.
+
+@ifclear BARETARGET
+@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}}.
+@end ifclear
+
+@ifset REMOTESTUB
+@item target remote @var{dev}
+@kindex target remote
+Remote serial target in GDB-specific protocol. The argument @var{dev}
+specifies what serial device to use for the connection (e.g.
+@file{/dev/ttya}). @xref{Remote, ,Remote debugging}.
+@end ifset
+
+@ifset SIMS
+@item target sim
+@kindex target sim
+CPU simulator. @xref{Simulator,,Simulated CPU Target}.
+@end ifset
+
+@ifset AMD29K
+@item target udi @var{keyword}
+@kindex target udi
+Remote AMD29K target, using the AMD UDI protocol. The @var{keyword}
+argument specifies which 29K board or simulator to use. @xref{UDI29K
+Remote,,@value{GDBN} and the UDI protocol for 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 @code{target remote};
+@var{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, ,@value{GDBN} with a remote EB29K}.
+
+@end ifset
+@ifset H8
+@item target hms
+@kindex target hms
+A Hitachi SH, H8/300, or H8/500 board, attached via serial line to your host.
+@ifclear H8EXCLUSIVE
+@c Unix only, not currently of interest for H8-only manual
+Use special commands @code{device} and @code{speed} to control the serial
+line and the communications speed used.
+@end ifclear
+@xref{Hitachi Remote,,@value{GDBN} and Hitachi Microprocessors}.
+
+@end ifset
+@ifset 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.
+@file{/dev/ttya}. @xref{i960-Nindy Remote, ,@value{GDBN} with a remote i960 (Nindy)}.
+
+@end ifset
+@ifset ST2000
+@item target st2000 @var{dev} @var{speed}
+@kindex target st2000
+A Tandem ST2000 phone switch, running Tandem's STDBUG protocol. @var{dev}
+is the name of the device attached to the ST2000 serial line;
+@var{speed} is the communication line speed. The arguments are not used
+if @value{GDBN} is configured to connect to the ST2000 using TCP or Telnet.
+@xref{ST2000 Remote,,@value{GDBN} with a Tandem ST2000}.
+
+@end ifset
+@ifset 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.
+@xref{VxWorks Remote, ,@value{GDBN} and VxWorks}.
+@end ifset
+@end table
+
+@ifset GENERIC
+Different targets are available on different configurations of @value{GDBN}; your
+configuration may have more or fewer targets.
+@end ifset
+
+@node Remote
+@section Remote debugging
+@cindex remote debugging
+
+If you are trying to debug a program running on a machine that cannot run
+GDB in the usual way, it is often useful to use remote debugging. For
+example, you might use remote debugging on an operating system kernel, or on
+a small system which does not have a general purpose operating system
+powerful enough to run a full-featured debugger.
+
+Some configurations of GDB have special serial or TCP/IP interfaces
+to make this work with particular debugging targets. In addition,
+GDB comes with a generic serial protocol (specific to GDB, but
+not specific to any particular target system) which you can use if you
+write the remote stubs---the code that will run on the remote system to
+communicate with GDB.
+
+Other remote targets may be available in your
+configuration of GDB; use @code{help targets} to list them.
+
+@ifset GENERIC
+@c Text on starting up GDB in various specific cases; it goes up front
+@c in manuals configured for any of those particular situations, here
+@c otherwise.
+@menu
+@ifset REMOTESTUB
+* Remote Serial:: @value{GDBN} remote serial protocol
+@end ifset
+@ifset I960
+* i960-Nindy Remote:: @value{GDBN} with a remote i960 (Nindy)
+@end ifset
+@ifset AMD29K
+* UDI29K Remote:: @value{GDBN} and the UDI protocol for AMD29K
+* EB29K Remote:: @value{GDBN} with a remote EB29K
+@end ifset
+@ifset VXWORKS
+* VxWorks Remote:: @value{GDBN} and VxWorks
+@end ifset
+@ifset ST2000
+* ST2000 Remote:: @value{GDBN} with a Tandem ST2000
+@end ifset
+@ifset H8
+* Hitachi Remote:: @value{GDBN} and Hitachi Microprocessors
+@end ifset
+@ifset MIPS
+* MIPS Remote:: @value{GDBN} and MIPS boards
+@end ifset
+@ifset SIMS
+* Simulator:: Simulated CPU target
+@end ifset
+@end menu
+
+@include remote.texi
+@end ifset
+
+@node Controlling GDB
+@chapter Controlling @value{GDBN}
+
+You can alter the way @value{GDBN} interacts with you by using
+the @code{set} command. For commands controlling how @value{GDBN} displays
+data, @pxref{Print Settings, ,Print settings}; other settings are described here.
+
+@menu
+* Prompt:: Prompt
+* Editing:: Command editing
+* History:: Command history
+* Screen Size:: Screen size
+* Numbers:: Numbers
+* Messages/Warnings:: Optional warnings and messages
+@end menu
+
+@node Prompt
+@section Prompt
+@cindex prompt
+
+@value{GDBN} indicates its readiness to read a command by printing a string
+called the @dfn{prompt}. This string is normally @samp{(@value{GDBP})}. You
+can change the prompt string with the @code{set prompt} command. For
+instance, when debugging @value{GDBN} with @value{GDBN}, it is useful to change
+the prompt in one of the @value{GDBN} sessions so that you can always tell which
+one you are talking to.
+
+@table @code
+@item set prompt @var{newprompt}
+@kindex set prompt
+Directs @value{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
+
+@value{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 @code{emacs}-style
+or @code{vi}-style inline editing of commands, @code{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 @value{GDBN} with the
+command @code{set}.
+
+@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.
+@end table
+
+@node History
+@section Command history
+
+@value{GDBN} can keep track of the commands you type during your
+debugging sessions, so that you can be certain of precisely what
+happened. Use these commands to manage the @value{GDBN} command
+history facility.
+
+@table @code
+@cindex history substitution
+@cindex history file
+@kindex set history filename
+@item set history filename @var{fname}
+Set the name of the @value{GDBN} command history file to @var{fname}. This is
+the file from which @value{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 environment variable @code{GDBHISTFILE}, or to
+@file{./.gdb_history} if this variable is not set.
+
+@cindex history save
+@kindex set history save
+@item set history save
+@itemx set history save on
+Record command history in a file, whose name may be specified with the
+@code{set history filename} command. By default, this option is disabled.
+
+@item set history save 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 @value{GDBN} will keep in its history list.
+This defaults to the value of the environment 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 @kbd{!}.
+@ifset have-readline-appendices
+@xref{Event Designators}.
+@end ifset
+
+Since @kbd{!} is also the logical not operator in C, history expansion
+is off by default. If you decide to enable history expansion with the
+@code{set history expansion on} command, you may sometimes need to
+follow @kbd{!} (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
+@kbd{!=} and @kbd{!(}, 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 @code{emacs}
+or @code{vi} may wish to read it.
+@ifset have-readline-appendices
+@xref{Command Line Editing}.
+@end ifset
+
+@c @group
+@kindex show history
+@item show history
+@itemx show history filename
+@itemx show history save
+@itemx show history size
+@itemx show history expansion
+These commands display the state of the @value{GDBN} history parameters.
+@code{show history} by itself displays all four states.
+@c @end group
+@end table
+
+@table @code
+@kindex show commands
+@item show commands
+Display the last ten commands in the command history.
+
+@item show commands @var{n}
+Print ten commands centered on command number @var{n}.
+
+@item show commands +
+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 @value{GDBN} may produce large amounts of
+information output to the screen. To help you read all of it,
+@value{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, or @kbd{q}
+to discard the remaining output. Also, the screen width setting
+determines when to wrap lines of output. Depending on what is being
+printed, @value{GDBN} tries to break the line at a readable place,
+rather than simply letting it overflow onto the following line.
+
+Normally @value{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 @code{set height} and @code{set
+width} commands:
+
+@table @code
+@item set height @var{lpp}
+@itemx show height
+@itemx set width @var{cpl}
+@itemx show width
+@kindex set height
+@kindex set width
+@kindex show width
+@kindex show height
+These @code{set} commands specify a screen height of @var{lpp} lines and
+a screen width of @var{cpl} characters. The associated @code{show}
+commands display the current settings.
+
+If you specify a height of zero lines, @value{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.
+
+Likewise, you can specify @samp{set width 0} to prevent @value{GDBN}
+from wrapping its output.
+@end table
+
+@node Numbers
+@section Numbers
+@cindex number representation
+@cindex entering numbers
+
+You can always enter numbers in octal, decimal, or hexadecimal in @value{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 @code{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, or 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, @value{GDBN} is silent about its inner workings. If you are running
+on a slow machine, you may want to use the @code{set verbose} command.
+It will make @value{GDBN} tell you when it does a lengthy internal operation, so
+you will not think it has crashed.
+
+Currently, the messages controlled by @code{set verbose} are those
+which announce that the symbol table for a source file is being read;
+see @code{symbol-file} in @ref{Files, ,Commands to specify files}.
+
+@table @code
+@kindex set verbose
+@item set verbose on
+Enables @value{GDBN} output of certain informational messages.
+
+@item set verbose off
+Disables @value{GDBN} output of certain informational messages.
+
+@kindex show verbose
+@item show verbose
+Displays whether @code{set verbose} is on or off.
+@end table
+
+By default, if @value{GDBN} encounters bugs in the symbol table of an object
+file, it is silent; but if you are debugging a compiler, you may find
+this information useful (@pxref{Symbol Errors, ,Errors reading symbol files}).
+
+@table @code
+@kindex set complaints
+@item set complaints @var{limit}
+Permits @value{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 @value{GDBN} is permitted to produce.
+@end table
+
+By default, @value{GDBN} is cautious, and asks what sometimes seems to be a
+lot of stupid questions to confirm certain commands. For example, if
+you try to run a program which is already running:
+
+@example
+(@value{GDBP}) run
+The program being debugged has been started already.
+Start it from the beginning? (y or n)
+@end example
+
+If you are willing to unflinchingly face the consequences of your own
+commands, you can disable this ``feature'':
+
+@table @code
+@kindex set confirm
+@cindex flinching
+@cindex confirmation
+@cindex stupid questions
+@item set confirm off
+Disables confirmation requests.
+
+@item set confirm on
+Enables confirmation requests (the default).
+
+@item show confirm
+@kindex show confirm
+Displays state of confirmation requests.
+@end table
+
+@c FIXME this does not really belong here. But where *does* it belong?
+@cindex reloading symbols
+Some systems allow individual object files that make up your program to
+be replaced without stopping and restarting your program.
+@ifset VXWORKS
+For example, in VxWorks you can simply recompile a defective object file
+and keep on running.
+@end ifset
+If you are running on one of these systems, you can allow @value{GDBN} to
+reload the symbols for automatically relinked modules:
+
+@table @code
+@kindex set symbol-reloading
+@item set symbol-reloading on
+Replace symbol definitions for the corresponding source file when an
+object file with a particular name is seen again.
+
+@item set symbol-reloading off
+Do not replace symbol definitions when re-encountering object files of
+the same name. This is the default state; if you are not running on a
+system that permits automatically relinking modules, you should leave
+@code{symbol-reloading} off, since otherwise @value{GDBN} may discard symbols
+when linking large programs, that may contain several modules (from
+different directories or libraries) with the same name.
+
+@item show symbol-reloading
+Show the current @code{on} or @code{off} setting.
+@end table
+
+@node Sequences
+@chapter Canned Sequences of Commands
+
+Aside from breakpoint commands (@pxref{Break Commands, ,Breakpoint
+command lists}), @value{GDBN} provides two ways to store sequences of commands
+for execution as a unit: user-defined commands and command files.
+
+@menu
+* Define:: User-defined commands
+* Hooks:: User-defined command hooks
+* Command Files:: Command files
+* Output:: Commands for controlled output
+@end menu
+
+@node Define
+@section User-defined commands
+
+@cindex user-defined command
+A @dfn{user-defined command} is a sequence of @value{GDBN} commands to which you
+assign a new name as a command. This is done with the @code{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 @value{GDBN} command lines,
+which are given following the @code{define} command. The end of these
+commands is marked by a line containing @code{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 @code{define} reads the lines of the
+command definition, ending with @code{end}. After the @code{document}
+command is finished, @code{help} on command @var{commandname} will print
+the documentation you have specified.
+
+You may use the @code{document} command again to change the
+documentation of a command. Redefining the command with @code{define}
+does not change the documentation.
+
+@item help user-defined
+@kindex help user-defined
+List all user-defined commands, with the first line of the documentation
+(if any) for each.
+
+@item show user
+@itemx show user @var{commandname}
+@kindex show user
+Display the @value{GDBN} commands used to define @var{commandname} (but not its
+documentation). If no @var{commandname} is given, display the
+definitions for all user-defined commands.
+@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 @value{GDBN} commands
+that normally print messages to say what they are doing omit the messages
+when used in a user-defined command.
+
+@node Hooks
+@section User-defined command hooks
+@cindex command files
+
+You may define @emph{hooks}, which are a special kind of user-defined
+command. Whenever you run the command @samp{foo}, if the user-defined
+command @samp{hook-foo} exists, it is executed (with no arguments)
+before that command.
+
+In addition, a pseudo-command, @samp{stop} exists. Defining
+(@samp{hook-stop}) makes the associated commands execute every time
+execution stops in your program: before breakpoint commands are run,
+displays are printed, or the stack frame is printed.
+
+@ifclear BARETARGET
+For example, to ignore @code{SIGALRM} signals while
+single-stepping, but treat them normally during normal execution,
+you could define:
+
+@example
+define hook-stop
+handle SIGALRM nopass
+end
+
+define hook-run
+handle SIGALRM pass
+end
+
+define hook-continue
+handle SIGLARM pass
+end
+@end example
+@end ifclear
+
+You can define a hook for any single-word command in @value{GDBN}, but
+not for command aliases; you should define a hook for the basic command
+name, e.g. @code{backtrace} rather than @code{bt}.
+@c FIXME! So how does Joe User discover whether a command is an alias
+@c or not?
+If an error occurs during the execution of your hook, execution of
+@value{GDBN} commands stops and @value{GDBN} issues a prompt
+(before the command that you actually typed had a chance to run).
+
+If you try to define a hook which does not match any known command, you
+will get a warning from the @code{define} command.
+
+@node Command Files
+@section Command files
+
+@cindex command files
+A command file for @value{GDBN} is a file of lines that are @value{GDBN} commands. Comments
+(lines starting with @kbd{#}) 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{@value{GDBINIT}}
+When you start @value{GDBN}, it automatically executes commands from its
+@dfn{init files}. These are files named @file{@value{GDBINIT}}. @value{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 you use the @samp{-nx} option; @pxref{Mode Options,
+,Choosing modes}.)
+
+@ifset GENERIC
+@cindex init file name
+On some configurations of @value{GDBN}, the init file is known by a
+different name (these are typically environments where a specialized
+form of GDB may need to coexist with other forms, hence a different name
+for the specialized version's init file). These are the environments
+with special init file names:
+
+@itemize @bullet
+@kindex .vxgdbinit
+@item
+VxWorks (Wind River Systems real-time OS): @samp{.vxgdbinit}
+
+@kindex .os68gdbinit
+@item
+OS68K (Enea Data Systems real-time OS): @samp{.os68gdbinit}
+
+@kindex .esgdbinit
+@item
+ES-1800 (Ericsson Telecom AB M68000 emulator): @samp{.esgdbinit}
+@end itemize
+@end ifset
+
+You can also request the execution of a command file with the
+@code{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 @value{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, normal
+@value{GDBN} output is suppressed; the only output that appears is what is
+explicitly printed by the commands in the definition. This section
+describes three commands useful for generating exactly the output you
+want.
+
+@table @code
+@item echo @var{text}
+@kindex echo
+@c I do not consider backslash-space a standard C escape sequence
+@c because it is 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. @strong{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 displaying a
+string with spaces at the beginning or the end, since leading and
+trailing spaces are otherwise trimmed from all arguments.
+To print @samp{@w{ }and foo =@w{ }}, use the command
+@samp{echo \@w{ }and foo = \@w{ }}.
+
+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, ,Expressions}, for more information on
+expressions.
+
+@item output/@var{fmt} @var{expression}
+Print the value of @var{expression} in format @var{fmt}. You can use
+the same formats as for @code{print}. @xref{Output Formats,,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 your program were to execute the C
+subroutine
+
+@example
+printf (@var{string}, @var{expressions}@dots{});
+@end example
+
+For example, you can print two values in hex like this:
+
+@smallexample
+printf "foo, bar-foo = 0x%x, 0x%x\n", foo, bar-foo
+@end smallexample
+
+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
+
+@ifclear DOSHOST
+@node Emacs
+@chapter Using @value{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
+@value{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
+@value{GDBN} as a subprocess of Emacs, with input and output through a newly
+created Emacs buffer.
+
+Using @value{GDBN} under Emacs is just like using @value{GDBN} normally except for two
+things:
+
+@itemize @bullet
+@item
+All ``terminal'' input and output goes through the Emacs buffer.
+@end itemize
+
+This applies both to @value{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 interacting
+with your program. In particular, you can send signals the usual
+way---for example, @kbd{C-c C-c} for an interrupt, @kbd{C-c C-z} for a
+stop.
+
+@itemize @bullet
+@item
+@value{GDBN} displays source code through Emacs.
+@end itemize
+
+Each time @value{GDBN} displays a stack frame, Emacs automatically finds the
+source file for that frame and puts an arrow (@samp{=>}) at the
+left margin of the current line. Emacs uses a separate buffer for
+source display, and splits the screen to show both your @value{GDBN} session
+and the source.
+
+Explicit @value{GDBN} @code{list} or search commands still produce output as
+usual, but you probably will have no reason to use them.
+
+@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. @value{GDBN} can find programs by searching your
+environment's @code{PATH} variable, so the @value{GDBN} input and output
+session will proceed normally; but Emacs does not get enough information
+back from @value{GDBN} to locate the source files in this situation. To
+avoid this problem, either start @value{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 @value{GDBN} @code{file} command to
+switch to debugging a program in some other location, from an existing
+@value{GDBN} buffer in Emacs.
+@end quotation
+
+By default, @kbd{M-x gdb} calls the program called @file{gdb}. If
+you need to call @value{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 @file{.emacs} file) will make Emacs call the program named
+``@code{mygdb}'' instead.
+
+In the @value{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' @value{GDBN} Mode.
+
+@item M-s
+Execute to another source line, like the @value{GDBN} @code{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 @value{GDBN} @code{next} command. Then update the display window
+to show the current file and location.
+
+@item M-i
+Execute one instruction, like the @value{GDBN} @code{stepi} command; update
+display window accordingly.
+
+@item M-x gdb-nexti
+Execute to next instruction, using the @value{GDBN} @code{nexti} command; update
+display window accordingly.
+
+@item C-c C-f
+Execute until exit from the selected stack frame, like the @value{GDBN}
+@code{finish} command.
+
+@item M-c
+Continue execution of your program, like the @value{GDBN} @code{continue}
+command.
+
+@emph{Warning:} In Emacs v19, this command is @kbd{C-c C-p}.
+
+@item M-u
+Go up the number of frames indicated by the numeric argument
+(@pxref{Arguments, , Numeric Arguments, emacs, The GNU Emacs Manual}),
+like the @value{GDBN} @code{up} command.
+
+@emph{Warning:} In Emacs v19, this command is @kbd{C-c C-u}.
+
+@item M-d
+Go down the number of frames indicated by the numeric argument, like the
+@value{GDBN} @code{down} command.
+
+@emph{Warning:} In Emacs v19, this command is @kbd{C-c C-d}.
+
+@item C-x &
+Read the number where the cursor is positioned, and insert it at the end
+of the @value{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 @code{disassemble} by typing @kbd{C-x &}.
+
+You can customize this further by defining elements of the list
+@code{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 indicate 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 @code{format}; otherwise the number
+is passed as an argument to the corresponding list element.
+@end table
+
+In any source file, the Emacs command @kbd{C-x SPC} (@code{gdb-break})
+tells @value{GDBN} to set a breakpoint on the source line point is on.
+
+If you accidentally delete the source-display buffer, an easy way to get
+it back is to type the command @code{f} in the @value{GDBN} buffer, to
+request a frame display; when you run under Emacs, this will recreate
+the source buffer if necessary to show you the context of the current
+frame.
+
+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 @value{GDBN}
+communicates with Emacs in terms of line numbers. If you add or
+delete lines from the text, the line numbers that @value{GDBN} knows will cease
+to correspond properly with the code.
+
+@c The following dropped because Epoch is nonstandard. Reactivate
+@c 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 @code{epoch}
+environment. Users of this environment can use a new command,
+@code{inspect} which performs identically to @code{print} except that
+each value is printed in its own window.
+@end ignore
+@end ifclear
+
+@ifset LUCID
+@node Energize
+@chapter Using @value{GDBN} with Energize
+
+@cindex Energize
+The Energize Programming System is an integrated development environment
+that includes a point-and-click interface to many programming tools.
+When you use @value{GDBN} in this environment, you can use the standard
+Energize graphical interface to drive @value{GDBN}; you can also, if you
+choose, type @value{GDBN} commands as usual in a debugging window. Even if
+you use the graphical interface, the debugging window (which uses Emacs,
+and resembles the standard Emacs interface to @value{GDBN}) displays the
+equivalent commands, so that the history of your debugging session is
+properly reflected.
+
+When Energize starts up a @value{GDBN} session, it uses one of the
+command-line options @samp{-energize} or @samp{-cadillac} (``cadillac''
+is the name of the communications protocol used by the Energize system).
+This option makes @value{GDBN} run as one of the tools in the Energize Tool
+Set: it sends all output to the Energize kernel, and accept input from
+it as well.
+
+See the user manual for the Energize Programming System for
+information on how to use the Energize graphical interface and the other
+development tools that Energize integrates with @value{GDBN}.
+
+@end ifset
+
+@node GDB Bugs
+@chapter Reporting Bugs in @value{GDBN}
+@cindex bugs in @value{GDBN}
+@cindex reporting bugs in @value{GDBN}
+
+Your bug reports play an essential role in making @value{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 @value{GDBN} work better. Bug
+reports are your contribution to the maintenance of @value{GDBN}.
+
+In order for a bug report to serve its purpose, you must include the
+information that enables us to fix the bug.
+
+@menu
+* Bug Criteria:: Have you found a bug?
+* Bug Reporting:: How to report bugs
+@end menu
+
+@node Bug Criteria
+@section Have you found a bug?
+@cindex bug criteria
+
+If you are not sure whether you have found a bug, here are some guidelines:
+
+@itemize @bullet
+@item
+@cindex fatal signal
+@cindex debugger crash
+@cindex crash of debugger
+If the debugger gets a fatal signal, for any input whatever, that is a
+@value{GDBN} bug. Reliable debuggers never crash.
+
+@item
+@cindex error on valid input
+If @value{GDBN} produces an error message for valid input, that is a bug.
+
+@item
+@cindex invalid input
+If @value{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 @value{GDBN} are welcome in any case.
+@end itemize
+
+@node Bug Reporting
+@section How to report bugs
+@cindex bug reports
+@cindex @value{GDBN} bugs, reporting
+
+A number of companies and individuals offer support for GNU products.
+If you obtained @value{GDBN} from a support organization, we recommend you
+contact that organization first.
+
+You can find contact information for many support companies and
+individuals in the file @file{etc/SERVICE} in the GNU Emacs
+distribution.
+
+In any event, we also recommend that you send bug reports for @value{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 @value{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 @samp{gnu.gdb.bug} 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 often lacks 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
+Free Software Foundation
+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 do not matter. Thus, you might
+assume that the name of the variable you use in an example does not matter.
+Well, probably it does not, but one cannot be sure. Perhaps the bug is a
+stray memory reference which happens to fetch from the location where that
+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 is not as important as 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 @value{GDBN}. @value{GDBN} announces it if you start with no
+arguments; you can also print it at any time using @code{show version}.
+
+Without this, we will not know whether there is any point in looking for
+the bug in the current version of @value{GDBN}.
+
+@item
+The type of machine you are using, and the operating system name and
+version number.
+
+@item
+What compiler (and its version) was used to compile @value{GDBN}---e.g.
+``@value{GCC}--2.0''.
+
+@item
+What compiler (and its version) was used to compile the program you
+are debugging---e.g. ``@value{GCC}--2.0''.
+
+@item
+The command arguments you gave the compiler to compile your example and
+observe the bug. For example, did you use @samp{-O}? To guarantee
+you will not omit something important, list them all. A copy of the
+Makefile (or the output from make) is sufficient.
+
+If we were to try to guess the arguments, we would probably guess wrong
+and then we might not encounter the bug.
+
+@item
+A complete input script, and all necessary source files, that will
+reproduce the bug.
+
+@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 @value{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. We are human, after all. You
+might as well not give us a chance to make a mistake.
+
+Even if the problem you experience is a fatal signal, you should still
+say so explicitly. Suppose something strange is going on, such as,
+your copy of @value{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 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 @value{GDBN} source, send us context
+diffs. If you even discuss something in the @value{GDBN} source, refer to
+it by context, not by line number.
+
+The line numbers in our development sources will not match those in your
+sources. Your line numbers would convey no useful information to us.
+@end itemize
+
+Here are some things that are not necessary:
+
+@itemize @bullet
+@item
+A description of the envelope of the bug.
+
+Often people who encounter a bug spend a lot of time investigating
+which changes to the input file will make the bug go away and which
+changes will not affect it.
+
+This is often time consuming and not very useful, because the way we
+will find the bug is by running a single example under the debugger
+with breakpoints, not by pure deduction from a series of examples.
+We recommend that you save your time for something else.
+
+Of course, if you can find a simpler example to report @emph{instead}
+of the original one, that is a convenience for us. Errors in the
+output will be easier to spot, running under the debugger will take
+less time, etc.
+
+However, simplification is not vital; if you do not want to do this,
+report the bug anyway and send us the entire test case you used.
+
+@item
+A patch for the bug.
+
+A patch for the bug does help us if it is a good one. But do not omit
+the necessary information, such as the test case, on the assumption that
+a patch is all we need. We might see problems with your patch and decide
+to fix the problem another way, or we might not understand it at all.
+
+Sometimes with a program as complicated as @value{GDBN} it is very hard to
+construct an example that will make the program follow a certain path
+through the code. If you do not send us the example, we will not be able
+to construct one, so we will not be able to verify that the bug is fixed.
+
+And if we cannot understand what bug you are trying to fix, or why your
+patch should be an improvement, we will not install it. A test case will
+help us to understand.
+
+@item
+A guess about what the bug is or what it depends on.
+
+Such guesses are usually wrong. Even we cannot guess right about such
+things without first using the debugger to find the facts.
+@end itemize
+
+@c The readline documentation is distributed with the readline code
+@c and consists of the two following files:
+@c rluser.texinfo
+@c inc-hist.texi
+@c Use -I with makeinfo to point to the appropriate directory,
+@c environment var TEXINPUTS with TeX.
+@include rluser.texinfo
+@include inc-hist.texi
+
+@ifset NOVEL
+@node Renamed Commands
+@appendix Renamed Commands
+
+The following commands were renamed in GDB 4, in order to make the
+command set as a whole more consistent and easier to use and remember:
+
+@kindex add-syms
+@kindex delete environment
+@kindex info copying
+@kindex info convenience
+@kindex info directories
+@kindex info editing
+@kindex info history
+@kindex info targets
+@kindex info values
+@kindex info version
+@kindex info warranty
+@kindex set addressprint
+@kindex set arrayprint
+@kindex set prettyprint
+@kindex set screen-height
+@kindex set screen-width
+@kindex set unionprint
+@kindex set vtblprint
+@kindex set demangle
+@kindex set asm-demangle
+@kindex set sevenbit-strings
+@kindex set array-max
+@kindex set caution
+@kindex set history write
+@kindex show addressprint
+@kindex show arrayprint
+@kindex show prettyprint
+@kindex show screen-height
+@kindex show screen-width
+@kindex show unionprint
+@kindex show vtblprint
+@kindex show demangle
+@kindex show asm-demangle
+@kindex show sevenbit-strings
+@kindex show array-max
+@kindex show caution
+@kindex show history write
+@kindex unset
+
+@c TEXI2ROFF-KILL
+@ifinfo
+@c END TEXI2ROFF-KILL
+@example
+OLD COMMAND NEW COMMAND
+@c TEXI2ROFF-KILL
+--------------- -------------------------------
+@c END TEXI2ROFF-KILL
+add-syms add-symbol-file
+delete environment unset environment
+info convenience show convenience
+info copying show copying
+info directories show directories
+info editing show commands
+info history show values
+info targets help target
+info values show values
+info version show version
+info warranty show warranty
+set/show addressprint set/show print address
+set/show array-max set/show print elements
+set/show arrayprint set/show print array
+set/show asm-demangle set/show print asm-demangle
+set/show caution set/show confirm
+set/show demangle set/show print demangle
+set/show history write set/show history save
+set/show prettyprint set/show print pretty
+set/show screen-height set/show height
+set/show screen-width set/show width
+set/show sevenbit-strings set/show print sevenbit-strings
+set/show unionprint set/show print union
+set/show vtblprint set/show print vtbl
+
+unset [No longer an alias for delete]
+@end example
+@c TEXI2ROFF-KILL
+@end ifinfo
+
+@tex
+\vskip \parskip\vskip \baselineskip
+\halign{\tt #\hfil &\qquad#&\tt #\hfil\cr
+{\bf Old Command} &&{\bf New Command}\cr
+add-syms &&add-symbol-file\cr
+delete environment &&unset environment\cr
+info convenience &&show convenience\cr
+info copying &&show copying\cr
+info directories &&show directories \cr
+info editing &&show commands\cr
+info history &&show values\cr
+info targets &&help target\cr
+info values &&show values\cr
+info version &&show version\cr
+info warranty &&show warranty\cr
+set{\rm / }show addressprint &&set{\rm / }show print address\cr
+set{\rm / }show array-max &&set{\rm / }show print elements\cr
+set{\rm / }show arrayprint &&set{\rm / }show print array\cr
+set{\rm / }show asm-demangle &&set{\rm / }show print asm-demangle\cr
+set{\rm / }show caution &&set{\rm / }show confirm\cr
+set{\rm / }show demangle &&set{\rm / }show print demangle\cr
+set{\rm / }show history write &&set{\rm / }show history save\cr
+set{\rm / }show prettyprint &&set{\rm / }show print pretty\cr
+set{\rm / }show screen-height &&set{\rm / }show height\cr
+set{\rm / }show screen-width &&set{\rm / }show width\cr
+set{\rm / }show sevenbit-strings &&set{\rm / }show print sevenbit-strings\cr
+set{\rm / }show unionprint &&set{\rm / }show print union\cr
+set{\rm / }show vtblprint &&set{\rm / }show print vtbl\cr
+\cr
+unset &&\rm(No longer an alias for delete)\cr
+}
+@end tex
+@c END TEXI2ROFF-KILL
+@end ifset
+
+@ifclear PRECONFIGURED
+@node Formatting Documentation
+@appendix Formatting Documentation
+
+@cindex GDB reference card
+@cindex reference card
+The GDB 4 release includes an already-formatted reference card, ready
+for printing with PostScript or GhostScript, in the @file{gdb}
+subdirectory of the main source directory@footnote{In
+@file{gdb-@value{GDBVN}/gdb/refcard.ps} of the version @value{GDBVN}
+release.}. If you can use PostScript or GhostScript with your printer,
+you can print the reference card immediately with @file{refcard.ps}.
+
+The release also includes the source for the reference card. You
+can format it, using @TeX{}, by typing:
+
+@example
+make refcard.dvi
+@end example
+
+The GDB reference card is designed to print in landscape mode on US
+``letter'' size paper; that is, on a sheet 11 inches wide by 8.5 inches
+high. You will need to specify this form of printing as an option to
+your @sc{dvi} output program.
+
+@cindex documentation
+
+All the documentation for GDB comes as part of the machine-readable
+distribution. The documentation is written in Texinfo format, which is
+a documentation system that uses a single source file to produce both
+on-line information and a printed manual. You can use one of the Info
+formatting commands to create the on-line version of the documentation
+and @TeX{} (or @code{texi2roff}) to typeset the printed version.
+
+GDB includes an already formatted copy of the on-line Info version of
+this manual in the @file{gdb} subdirectory. The main Info file is
+@file{gdb-@var{version-number}/gdb/gdb.info}, and it refers to
+subordinate files matching @samp{gdb.info*} in the same directory. If
+necessary, you can print out these files, or read them with any editor;
+but they are easier to read using the @code{info} subsystem in GNU Emacs
+or the standalone @code{info} program, available as part of the GNU
+Texinfo distribution.
+
+If you want to format these Info files yourself, you need one of the
+Info formatting programs, such as @code{texinfo-format-buffer} or
+@code{makeinfo}.
+
+If you have @code{makeinfo} installed, and are in the top level GDB
+source directory (@file{gdb-@value{GDBVN}}, in the case of version @value{GDBVN}), you can
+make the Info file by typing:
+
+@example
+cd gdb
+make gdb.info
+@end example
+
+If you want to typeset and print copies of this manual, you need @TeX{},
+a program to print its @sc{dvi} output files, and @file{texinfo.tex}, the
+Texinfo definitions file.
+
+@TeX{} is a typesetting program; it does not print files directly, but
+produces output files called @sc{dvi} files. To print a typeset
+document, you need a program to print @sc{dvi} files. If your system
+has @TeX{} installed, chances are it has such a program. The precise
+command to use depends on your system; @kbd{lpr -d} is common; another
+(for PostScript devices) is @kbd{dvips}. The @sc{dvi} print command may
+require a file name without any extension or a @samp{.dvi} extension.
+
+@TeX{} also requires a macro definitions file called
+@file{texinfo.tex}. This file tells @TeX{} how to typeset a document
+written in Texinfo format. On its own, @TeX{} cannot read, much less
+typeset a Texinfo file. @file{texinfo.tex} is distributed with GDB
+and is located in the @file{gdb-@var{version-number}/texinfo}
+directory.
+
+If you have @TeX{} and a @sc{dvi} printer program installed, you can
+typeset and print this manual. First switch to the the @file{gdb}
+subdirectory of the main source directory (for example, to
+@file{gdb-@value{GDBVN}/gdb}) and then type:
+
+@example
+make gdb.dvi
+@end example
+
+@node Installing GDB
+@appendix Installing GDB
+@cindex configuring GDB
+@cindex installation
+
+GDB comes with a @code{configure} script that automates the process
+of preparing GDB for installation; you can then use @code{make} to
+build the @code{gdb} program.
+@iftex
+@c irrelevant in info file; it's as current as the code it lives with.
+@footnote{If you have a more recent version of GDB than @value{GDBVN},
+look at the @file{README} file in the sources; we may have improved the
+installation procedures since publishing this manual.}
+@end iftex
+
+The GDB distribution includes all the source code you need for GDB in
+a single directory, whose name is usually composed by appending the
+version number to @samp{gdb}.
+
+For example, the GDB version @value{GDBVN} distribution is in the
+@file{gdb-@value{GDBVN}} directory. That directory contains:
+
+@table @code
+@item gdb-@value{GDBVN}/configure @r{(and supporting files)}
+script for configuring GDB and all its supporting libraries.
+
+@item gdb-@value{GDBVN}/gdb
+the source specific to GDB itself
+
+@item gdb-@value{GDBVN}/bfd
+source for the Binary File Descriptor library
+
+@item gdb-@value{GDBVN}/include
+GNU include files
+
+@item gdb-@value{GDBVN}/libiberty
+source for the @samp{-liberty} free software library
+
+@item gdb-@value{GDBVN}/opcodes
+source for the library of opcode tables and disassemblers
+
+@item gdb-@value{GDBVN}/readline
+source for the GNU command-line interface
+
+@item gdb-@value{GDBVN}/glob
+source for the GNU filename pattern-matching subroutine
+
+@item gdb-@value{GDBVN}/mmalloc
+source for the GNU memory-mapped malloc package
+@end table
+
+The simplest way to configure and build GDB is to run @code{configure}
+from the @file{gdb-@var{version-number}} source directory, which in
+this example is the @file{gdb-@value{GDBVN}} directory.
+
+First switch to the @file{gdb-@var{version-number}} source directory
+if you are not already in it; then run @code{configure}. Pass the
+identifier for the platform on which GDB will run as an
+argument.
+
+For example:
+
+@example
+cd gdb-@value{GDBVN}
+./configure @var{host}
+make
+@end example
+
+@noindent
+where @var{host} is an identifier such as @samp{sun4} or
+@samp{decstation}, that identifies the platform where GDB will run.
+(You can often leave off @var{host}; @code{configure} tries to guess the
+correct value by examining your system.)
+
+Running @samp{configure @var{host}} and then running @code{make} builds the
+@file{bfd}, @file{readline}, @file{mmalloc}, and @file{libiberty}
+libraries, then @code{gdb} itself. The configured source files, and the
+binaries, are left in the corresponding source directories.
+
+@code{configure} is a Bourne-shell (@code{/bin/sh}) script; if your
+system does not recognize this automatically when you run a different
+shell, you may need to run @code{sh} on it explicitly:
+
+@example
+sh configure @var{host}
+@end example
+
+If you run @code{configure} from a directory that contains source
+directories for multiple libraries or programs, such as the
+@file{gdb-@value{GDBVN}} source directory for version @value{GDBVN}, @code{configure}
+creates configuration files for every directory level underneath (unless
+you tell it not to, with the @samp{--norecursion} option).
+
+You can run the @code{configure} script from any of the
+subordinate directories in the GDB distribution if you only want to
+configure that subdirectory, but be sure to specify a path to it.
+
+For example, with version @value{GDBVN}, type the following to configure only
+the @code{bfd} subdirectory:
+
+@example
+@group
+cd gdb-@value{GDBVN}/bfd
+../configure @var{host}
+@end group
+@end example
+
+You can install @code{@value{GDBP}} anywhere; it has no hardwired paths.
+However, you should make sure that the shell on your path (named by
+the @samp{SHELL} environment variable) is publicly readable. Remember
+that GDB uses the shell to start your program---some systems refuse to
+let GDB debug child processes whose programs are not readable.
+
+@menu
+* Separate Objdir:: Compiling GDB in another directory
+* Config Names:: Specifying names for hosts and targets
+* configure Options:: Summary of options for configure
+@end menu
+
+@node Separate Objdir
+@section Compiling GDB in another directory
+
+If you want to run GDB versions for several host or target machines,
+you need a different @code{gdb} compiled for each combination of
+host and target. @code{configure} is designed to make this easy by
+allowing you to generate each configuration in a separate subdirectory,
+rather than in the source directory. If your @code{make} program
+handles the @samp{VPATH} feature (GNU @code{make} does), running
+@code{make} in each of these directories builds the @code{gdb}
+program specified there.
+
+To build @code{gdb} in a separate directory, run @code{configure}
+with the @samp{--srcdir} option to specify where to find the source.
+(You also need to specify a path to find @code{configure}
+itself from your working directory. If the path to @code{configure}
+would be the same as the argument to @samp{--srcdir}, you can leave out
+the @samp{--srcdir} option; it will be assumed.)
+
+For example, with version @value{GDBVN}, you can build GDB in a separate
+directory for a Sun 4 like this:
+
+@example
+@group
+cd gdb-@value{GDBVN}
+mkdir ../gdb-sun4
+cd ../gdb-sun4
+../gdb-@value{GDBVN}/configure sun4
+make
+@end group
+@end example
+
+When @code{configure} builds a configuration using a remote source
+directory, it creates a tree for the binaries with the same structure
+(and using the same names) as the tree under the source directory. In
+the example, you'd find the Sun 4 library @file{libiberty.a} in the
+directory @file{gdb-sun4/libiberty}, and GDB itself in
+@file{gdb-sun4/gdb}.
+
+One popular reason to build several GDB configurations in separate
+directories is to configure GDB for cross-compiling (where GDB
+runs on one machine---the host---while debugging programs that run on
+another machine---the target). You specify a cross-debugging target by
+giving the @samp{--target=@var{target}} option to @code{configure}.
+
+When you run @code{make} to build a program or library, you must run
+it in a configured directory---whatever directory you were in when you
+called @code{configure} (or one of its subdirectories).
+
+The @code{Makefile} that @code{configure} generates in each source
+directory also runs recursively. If you type @code{make} in a source
+directory such as @file{gdb-@value{GDBVN}} (or in a separate configured
+directory configured with @samp{--srcdir=@var{path}/gdb-@value{GDBVN}}), you
+will build all the required libraries, and then build GDB.
+
+When you have multiple hosts or targets configured in separate
+directories, you can run @code{make} on them in parallel (for example,
+if they are NFS-mounted on each of the hosts); they will not interfere
+with each other.
+
+@node Config Names
+@section Specifying names for hosts and targets
+
+The specifications used for hosts and targets in the @code{configure}
+script are based on a three-part naming scheme, but some short predefined
+aliases are also supported. The full naming scheme encodes three pieces
+of information in the following pattern:
+
+@example
+@var{architecture}-@var{vendor}-@var{os}
+@end example
+
+For example, you can use the alias @code{sun4} as a @var{host} argument,
+or as the value for @var{target} in a @code{--target=@var{target}}
+option. The equivalent full name is @samp{sparc-sun-sunos4}.
+
+The @code{configure} script accompanying GDB does not provide
+any query facility to list all supported host and target names or
+aliases. @code{configure} calls the Bourne shell script
+@code{config.sub} to map abbreviations to full names; you can read the
+script, if you wish, or you can use it to test your guesses on
+abbreviations---for example:
+
+@smallexample
+% sh config.sub sun4
+sparc-sun-sunos4.1.1
+% sh config.sub sun3
+m68k-sun-sunos4.1.1
+% sh config.sub decstation
+mips-dec-ultrix4.2
+% sh config.sub hp300bsd
+m68k-hp-bsd
+% sh config.sub i386v
+i386-unknown-sysv
+% sh config.sub i786v
+Invalid configuration `i786v': machine `i786v' not recognized
+@end smallexample
+
+@noindent
+@code{config.sub} is also distributed in the GDB source
+directory (@file{gdb-@value{GDBVN}}, for version @value{GDBVN}).
+
+@node configure Options
+@section @code{configure} options
+
+Here is a summary of the @code{configure} options and arguments that
+are most often useful for building @value{GDBN}. @code{configure} also has
+several other options not listed here. @inforef{What Configure
+Does,,configure.info}, for a full explanation of @code{configure}.
+@c FIXME: Would this be more, or less, useful as an xref (ref to printed
+@c manual in the printed manual, ref to info file only from the info file)?
+
+@example
+configure @r{[}--help@r{]}
+ @r{[}--prefix=@var{dir}@r{]}
+ @r{[}--srcdir=@var{path}@r{]}
+ @r{[}--norecursion@r{]} @r{[}--rm@r{]}
+ @r{[}--target=@var{target}@r{]} @var{host}
+@end example
+
+@noindent
+You may introduce options with a single @samp{-} rather than
+@samp{--} if you prefer; but you may abbreviate option names if you use
+@samp{--}.
+
+@table @code
+@item --help
+Display a quick summary of how to invoke @code{configure}.
+
+@item -prefix=@var{dir}
+Configure the source to install programs and files under directory
+@file{@var{dir}}.
+
+@item --srcdir=@var{path}
+@strong{Warning: using this option requires GNU @code{make}, or another
+@code{make} that implements the @code{VPATH} feature.}@*
+Use this option to make configurations in directories separate from the
+GDB source directories. Among other things, you can use this to
+build (or maintain) several configurations simultaneously, in separate
+directories. @code{configure} writes configuration specific files in
+the current directory, but arranges for them to use the source in the
+directory @var{path}. @code{configure} will create directories under
+the working directory in parallel to the source directories below
+@var{path}.
+
+@item --norecursion
+Configure only the directory level where @code{configure} is executed; do not
+propagate configuration to subdirectories.
+
+@item --rm
+@emph{Remove} files otherwise built during configuration.
+
+@c This does not work (yet if ever). FIXME.
+@c @item --parse=@var{lang} @dots{}
+@c Configure the GDB expression parser to parse the listed languages.
+@c @samp{all} configures GDB for all supported languages. To get a
+@c list of all supported languages, omit the argument. Without this
+@c option, GDB is configured to parse all supported languages.
+
+@item --target=@var{target}
+Configure GDB for cross-debugging programs running on the specified
+@var{target}. Without this option, GDB is configured to debug
+programs that run on the same machine (@var{host}) as GDB itself.
+
+There is no convenient way to generate a list of all available targets.
+
+@item @var{host} @dots{}
+Configure GDB to run on the specified @var{host}.
+
+There is no convenient way to generate a list of all available hosts.
+@end table
+
+@noindent
+@code{configure} accepts other options, for compatibility with
+configuring other GNU tools recursively; but these are the only
+options that affect GDB or its supporting libraries.
+@end ifclear
+
+@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\/},}
+\centerline{{\bf\fontname\tenbf}, and}
+\centerline{{\sl\fontname\tensl\/}}
+\centerline{are used for emphasis.}\vfill}
+\page\colophon
+% Blame: pesch@cygnus.com, 1991.
+@end tex
+
+@contents
+@bye
diff --git a/gnu/usr.bin/gdb/doc/gdbint.texinfo b/gnu/usr.bin/gdb/doc/gdbint.texinfo
new file mode 100644
index 000000000000..d158bac8f81a
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/gdbint.texinfo
@@ -0,0 +1,2658 @@
+\input texinfo
+@setfilename gdbint.info
+@c $Id: gdbint.texinfo,v 1.1 1994/06/10 13:34:28 paul Exp $
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Gdb-Internals: (gdbint). The GNU debugger's internals.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+This file documents the internals of the GNU debugger GDB.
+
+Copyright 1990, 1991, 1992, 1993 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 off
+@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: 1.1 $} % 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, 1992, 1993 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
+@c Perhaps this should be the title of the document (but only for info,
+@c not for TeX). Existing GNU manuals seem inconsistent on this point.
+@top Scope of this Document
+
+This document documents the internals of the GNU debugger, GDB. It is
+intended to document aspects of GDB which apply across many different
+parts of GDB (for example, @pxref{Coding Style}), or which are global
+aspects of design (for example, what are the major modules and which
+files document them in detail?). Information which pertains to specific
+data structures, functions, variables, etc., should be put in comments
+in the source code, not here. It is more likely to get noticed and kept
+up to date there. Some of the information in this document should
+probably be moved into comments.
+
+@menu
+* README:: The README File
+* Getting Started:: Getting started working on GDB
+* Debugging GDB:: Debugging GDB with itself
+* New Architectures:: Defining a New Host or Target Architecture
+* Config:: Adding a New Configuration
+* Host:: Adding a New Host
+* Native:: Adding a New Native Configuration
+* Target:: Adding a New Target
+* Languages:: Defining New Source Languages
+* Releases:: Configuring GDB for Release
+* Partial Symbol Tables:: How GDB reads symbols quickly at startup
+* Types:: How GDB keeps track of types
+* BFD support for GDB:: How BFD and GDB interface
+* Symbol Reading:: Defining New Symbol Readers
+* Cleanups:: Cleanups
+* Wrapping:: Wrapping Output Lines
+* Frames:: Keeping track of function calls
+* Remote Stubs:: Code that runs in targets and talks to GDB
+* Longjmp Support:: Stepping through longjmp's in the target
+* Coding Style:: Strunk and White for GDB maintainers
+* Clean Design:: Frank Lloyd Wright for GDB maintainers
+* Submitting Patches:: How to get your changes into GDB releases
+* Host Conditionals:: What features exist in the host
+* Target Conditionals:: What features exist in the target
+* Native Conditionals:: Conditionals for when host and target are same
+* Obsolete Conditionals:: Conditionals that don't exist any more
+* XCOFF:: The Object file format used on IBM's RS/6000
+@end menu
+
+@node README
+@chapter The @file{README} File
+
+Check the @file{README} file, it often has useful information that does not
+appear anywhere else in the directory.
+
+@node Getting Started
+@chapter Getting Started Working on GDB
+
+GDB is a large and complicated program, and if you first starting to
+work on it, it can be hard to know where to start. Fortunately, if you
+know how to go about it, there are ways to figure out what is going on:
+
+@itemize @bullet
+@item
+This manual, the GDB Internals manual, has information which applies
+generally to many parts of GDB.
+
+@item
+Information about particular functions or data structures are located in
+comments with those functions or data structures. If you run across a
+function or a global variable which does not have a comment correctly
+explaining what is does, this can be thought of as a bug in GDB; feel
+free to submit a bug report, with a suggested comment if you can figure
+out what the comment should say (@pxref{Submitting Patches}). If you
+find a comment which is actually wrong, be especially sure to report that.
+
+Comments explaining the function of macros defined in host, target, or
+native dependent files can be in several places. Sometimes they are
+repeated every place the macro is defined. Sometimes they are where the
+macro is used. Sometimes there is a header file which supplies a
+default definition of the macro, and the comment is there. This manual
+also has a list of macros (@pxref{Host Conditionals}, @pxref{Target
+Conditionals}, @pxref{Native Conditionals}, and @pxref{Obsolete
+Conditionals}) with some documentation.
+
+@item
+Start with the header files. Once you some idea of how GDB's internal
+symbol tables are stored (see @file{symtab.h}, @file{gdbtypes.h}), you
+will find it much easier to understand the code which uses and creates
+those symbol tables.
+
+@item
+You may wish to process the information you are getting somehow, to
+enhance your understanding of it. Summarize it, translate it to another
+language, add some (perhaps trivial or non-useful) feature to GDB, use
+the code to predict what a test case would do and write the test case
+and verify your prediction, etc. If you are reading code and your eyes
+are starting to glaze over, this is a sign you need to use a more active
+approach.
+
+@item
+Once you have a part of GDB to start with, you can find more
+specifically the part you are looking for by stepping through each
+function with the @code{next} command. Do not use @code{step} or you
+will quickly get distracted; when the function you are stepping through
+calls another function try only to get a big-picture understanding
+(perhaps using the comment at the beginning of the function being
+called) of what it does. This way you can identify which of the
+functions being called by the function you are stepping through is the
+one which you are interested in. You may need to examine the data
+structures generated at each stage, with reference to the comments in
+the header files explaining what the data structures are supposed to
+look like.
+
+Of course, this same technique can be used if you are just reading the
+code, rather than actually stepping through it. The same general
+principle applies---when the code you are looking at calls something
+else, just try to understand generally what the code being called does,
+rather than worrying about all its details.
+
+@item
+A good place to start when tracking down some particular area is with a
+command which invokes that feature. Suppose you want to know how
+single-stepping works. As a GDB user, you know that the @code{step}
+command invokes single-stepping. The command is invoked via command
+tables (see @file{command.h}); by convention the function which actually
+performs the command is formed by taking the name of the command and
+adding @samp{_command}, or in the case of an @code{info} subcommand,
+@samp{_info}. For example, the @code{step} command invokes the
+@code{step_command} function and the @code{info display} command invokes
+@code{display_info}. When this convention is not followed, you might
+have to use @code{grep} or @kbd{M-x tags-search} in emacs, or run GDB on
+itself and set a breakpoint in @code{execute_command}.
+
+@item
+If all of the above fail, it may be appropriate to ask for information
+on @code{bug-gdb}. But @emph{never} post a generic question like ``I was
+wondering if anyone could give me some tips about understanding
+GDB''---if we had some magic secret we would put it in this manual.
+Suggestions for improving the manual are always welcome, of course.
+@end itemize
+
+Good luck!
+
+@node Debugging GDB
+@chapter Debugging GDB with itself
+If gdb is limping on your machine, this is the preferred way to get it
+fully functional. Be warned that in some ancient Unix systems, like
+Ultrix 4.2, a program can't be running in one process while it is being
+debugged in another. Rather than typing the command @code{@w{./gdb
+./gdb}}, which works on Suns and such, you can copy @file{gdb} to
+@file{gdb2} and then type @code{@w{./gdb ./gdb2}}.
+
+When you run gdb in the gdb source directory, it will read a
+@file{.gdbinit} file that sets up some simple things to make debugging
+gdb easier. The @code{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 @file{.gdbinit} for details.
+
+If you use emacs, you will probably want to do a @code{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
+@kbd{M-.}
+
+Also, make sure that you've either compiled gdb with your local cc, or
+have run @code{fixincludes} if you are compiling with gcc.
+
+@node New Architectures
+@chapter Defining a New Host or Target Architecture
+
+When building support for a new host and/or target, much of the work you
+need to do is handled by specifying configuration files;
+@pxref{Config,,Adding a New Configuration}. Further work can be
+divided into ``host-dependent'' (@pxref{Host,,Adding a New Host}) and
+``target-dependent'' (@pxref{Target,,Adding a New Target}). The
+following discussion is meant to explain the difference between hosts
+and targets.
+
+@heading What is considered ``host-dependent'' versus ``target-dependent''?
+
+@dfn{Host} refers to attributes of the system where GDB runs.
+@dfn{Target} refers to the system where the program being debugged
+executes. In most cases they are the same machine, in which case
+a third type of @dfn{Native} attributes come into play.
+
+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.
+
+Defines and information needed to handle the target format are target
+dependent. Examples are the stack frame format, instruction set,
+breakpoint instruction, registers, and how to set up and tear down the stack
+to call a function.
+
+Information that is only needed when the host and target are the same,
+is native dependent. One example is Unix child process support; if the
+host and target are not the same, doing a fork to start the target
+process is a bad idea. The various macros needed for finding the
+registers in the @code{upage}, running @code{ptrace}, and such are all in the
+native-dependent files.
+
+Another example of native-dependent code is support for features
+that are really part of the target environment, but which require
+@code{#include} files that are only available on the host system.
+Core file handling and @code{setjmp} handling are two common cases.
+
+When you want to make GDB work ``native'' on a particular
+machine, you have to include all three kinds of information.
+
+The dependent information in GDB is organized into files by naming
+conventions.
+
+Host-Dependent Files
+@table @file
+@item config/*/*.mh
+Sets Makefile parameters
+@item config/*/xm-*.h
+Global #include's and #define's and definitions
+@item *-xdep.c
+Global variables and functions
+@end table
+
+Native-Dependent Files
+@table @file
+@item config/*/*.mh
+Sets Makefile parameters (for @emph{both} host and native)
+@item config/*/nm-*.h
+#include's and #define's and definitions. This file
+is only included by the small number of modules that need it,
+so beware of doing feature-test #define's from its macros.
+@item *-nat.c
+global variables and functions
+@end table
+
+Target-Dependent Files
+@table @file
+@item config/*/*.mt
+Sets Makefile parameters
+@item config/*/tm-*.h
+Global #include's and #define's and definitions
+@item *-tdep.c
+Global variables and functions
+@end table
+
+At this writing, most supported hosts have had their host and native
+dependencies sorted out properly. There are a few stragglers, which
+can be recognized by the absence of NATDEPFILES lines in their
+@file{config/*/*.mh}.
+
+@node Config
+@chapter Adding a New Configuration
+
+Most of the work in making GDB compile on a new machine is in specifying
+the configuration of the machine. This is done in a dizzying variety of
+header files and configuration scripts, which we hope to make more
+sensible soon. Let's say your new host is called an @var{xxx} (e.g.
+@samp{sun4}), and its full three-part configuration name is
+@code{@var{xarch}-@var{xvend}-@var{xos}} (e.g. @samp{sparc-sun-sunos4}). In
+particular:
+
+In the top level directory, edit @file{config.sub} and add @var{xarch},
+@var{xvend}, and @var{xos} to the lists of supported architectures,
+vendors, and operating systems near the bottom of the file. Also, add
+@var{xxx} as an alias that maps to
+@code{@var{xarch}-@var{xvend}-@var{xos}}. You can test your changes by
+running
+
+@example
+./config.sub @var{xxx}
+@end example
+@noindent
+and
+@example
+./config.sub @code{@var{xarch}-@var{xvend}-@var{xos}}
+@end example
+@noindent
+which should both respond with @code{@var{xarch}-@var{xvend}-@var{xos}}
+and no error messages.
+
+Now, go to the @file{bfd} directory and
+create a new file @file{bfd/hosts/h-@var{xxx}.h}. Examine the
+other @file{h-*.h} files as templates, and create one that brings in the
+right include files for your system, and defines any host-specific
+macros needed by BFD, the Binutils, GNU LD, or the Opcodes directories.
+(They all share the bfd @file{hosts} directory and the @file{configure.host}
+file.)
+
+Then edit @file{bfd/configure.host}. Add a line to recognize your
+@code{@var{xarch}-@var{xvend}-@var{xos}} configuration, and set
+@code{my_host} to @var{xxx} when you recognize it. This will cause your
+file @file{h-@var{xxx}.h} to be linked to @file{sysdep.h} at configuration
+time. When creating the line that recognizes your configuration,
+only match the fields that you really need to match; e.g. don't match
+match the architecture or manufacturer if the OS is sufficient
+to distinguish the configuration that your @file{h-@var{xxx}.h} file supports.
+Don't match the manufacturer name unless you really need to.
+This should make future ports easier.
+
+Also, if this host requires any changes to the Makefile, create a file
+@file{bfd/config/@var{xxx}.mh}, which includes the required lines.
+
+It's possible that the @file{libiberty} and @file{readline} directories
+won't need any changes for your configuration, but if they do, you can
+change the @file{configure.in} file there to recognize your system and
+map to an @file{mh-@var{xxx}} file. Then add @file{mh-@var{xxx}}
+to the @file{config/} subdirectory, to set any makefile variables you
+need. The only current options in there are things like @samp{-DSYSV}.
+(This @file{mh-@var{xxx}} naming convention differs from elsewhere
+in GDB, by historical accident. It should be cleaned up so that all
+such files are called @file{@var{xxx}.mh}.)
+
+Aha! Now to configure GDB itself! Edit
+@file{gdb/configure.in} to recognize your system and set @code{gdb_host}
+to @var{xxx}, and (unless your desired target is already available) also
+set @code{gdb_target} to something appropriate (for instance,
+@var{xxx}). To handle new hosts, modify the segment after the comment
+@samp{# per-host}; to handle new targets, modify after @samp{#
+per-target}.
+@c Would it be simpler to just use different per-host and per-target
+@c *scripts*, and call them from {configure} ?
+
+Finally, you'll need to specify and define GDB's host-, native-, and
+target-dependent @file{.h} and @file{.c} files used for your
+configuration; the next two chapters discuss those.
+
+
+@node Host
+@chapter Adding a New Host
+
+Once you have specified a new configuration for your host
+(@pxref{Config,,Adding a New Configuration}), there are three remaining
+pieces to making GDB work on a new machine. First, you have to make it
+host on the new machine (compile there, handle that machine's terminals
+properly, etc). If you will be cross-debugging to some other kind of
+system that's already supported, you are done.
+
+If you want to use GDB to debug programs that run on the new machine,
+you have to get it to understand the machine's object files, symbol
+files, and interfaces to processes; @pxref{Target,,Adding a New Target}
+and @pxref{Native,,Adding a New Native Configuration}
+
+Several files control GDB's configuration for host systems:
+
+@table @file
+@item gdb/config/@var{arch}/@var{xxx}.mh
+Specifies Makefile fragments needed when hosting on machine @var{xxx}.
+In particular, this lists the required machine-dependent object files,
+by defining @samp{XDEPFILES=@dots{}}. Also
+specifies the header file which describes host @var{xxx}, by defining
+@code{XM_FILE= xm-@var{xxx}.h}. You can also define @code{CC},
+@code{REGEX} and @code{REGEX1}, @code{SYSV_DEFINE}, @code{XM_CFLAGS},
+@code{XM_ADD_FILES}, @code{XM_CLIBS}, @code{XM_CDEPS},
+etc.; see @file{Makefile.in}.
+
+@item gdb/config/@var{arch}/xm-@var{xxx}.h
+(@file{xm.h} is a link to this file, created by configure).
+Contains C macro definitions describing the host system environment,
+such as byte order, host C compiler and library, ptrace support,
+and core file structure. Crib from existing @file{xm-*.h} files
+to create a new one.
+
+@item gdb/@var{xxx}-xdep.c
+Contains any miscellaneous C code required for this machine
+as a host. On many machines it doesn't exist at all. If it does
+exist, put @file{@var{xxx}-xdep.o} into the @code{XDEPFILES} line
+in @file{gdb/config/mh-@var{xxx}}.
+@end table
+
+@subheading Generic Host Support Files
+
+There are some ``generic'' versions of routines that can be used by
+various systems. These can be customized in various ways by macros
+defined in your @file{xm-@var{xxx}.h} file. If these routines work for
+the @var{xxx} host, you can just include the generic file's name (with
+@samp{.o}, not @samp{.c}) in @code{XDEPFILES}.
+
+Otherwise, if your machine needs custom support routines, you will need
+to write routines that perform the same functions as the generic file.
+Put them into @code{@var{xxx}-xdep.c}, and put @code{@var{xxx}-xdep.o}
+into @code{XDEPFILES}.
+
+@table @file
+@item ser-bsd.c
+This contains serial line support for Berkeley-derived Unix systems.
+
+@item ser-go32.c
+This contains serial line support for 32-bit programs running under DOS
+using the GO32 execution environment.
+
+@item ser-termios.c
+This contains serial line support for System V-derived Unix systems.
+@end table
+
+Now, you are now ready to try configuring GDB to compile using your system
+as its host. From the top level (above @file{bfd}, @file{gdb}, etc), do:
+
+@example
+./configure @var{xxx} +target=vxworks960
+@end example
+
+This will configure your system to cross-compile for VxWorks on
+the Intel 960, which is probably not what you really want, but it's
+a test case that works at this stage. (You haven't set up to be
+able to debug programs that run @emph{on} @var{xxx} yet.)
+
+If this succeeds, you can try building it all with:
+
+@example
+make
+@end example
+
+Repeat until the program configures, compiles, links, and runs.
+When run, it won't be able to do much (unless you have a VxWorks/960
+board on your network) but you will know that the host support is
+pretty well done.
+
+Good luck! Comments and suggestions about this section are particularly
+welcome; send them to @samp{bug-gdb@@prep.ai.mit.edu}.
+
+@node Native
+@chapter Adding a New Native Configuration
+
+If you are making GDB run native on the @var{xxx} machine, you have
+plenty more work to do. Several files control GDB's configuration for
+native support:
+
+@table @file
+@item gdb/config/@var{xarch}/@var{xxx}.mh
+Specifies Makefile fragments needed when hosting @emph{or native}
+on machine @var{xxx}.
+In particular, this lists the required native-dependent object files,
+by defining @samp{NATDEPFILES=@dots{}}. Also
+specifies the header file which describes native support on @var{xxx},
+by defining @samp{NAT_FILE= nm-@var{xxx}.h}.
+You can also define @samp{NAT_CFLAGS},
+@samp{NAT_ADD_FILES}, @samp{NAT_CLIBS}, @samp{NAT_CDEPS},
+etc.; see @file{Makefile.in}.
+
+@item gdb/config/@var{arch}/nm-@var{xxx}.h
+(@file{nm.h} is a link to this file, created by configure).
+Contains C macro definitions describing the native system environment,
+such as child process control and core file support.
+Crib from existing @file{nm-*.h} files to create a new one.
+
+@item gdb/@var{xxx}-nat.c
+Contains any miscellaneous C code required for this native support
+of this machine. On some machines it doesn't exist at all.
+@end table
+
+@subheading Generic Native Support Files
+
+There are some ``generic'' versions of routines that can be used by
+various systems. These can be customized in various ways by macros
+defined in your @file{nm-@var{xxx}.h} file. If these routines work for
+the @var{xxx} host, you can just include the generic file's name (with
+@samp{.o}, not @samp{.c}) in @code{NATDEPFILES}.
+
+Otherwise, if your machine needs custom support routines, you will need
+to write routines that perform the same functions as the generic file.
+Put them into @code{@var{xxx}-nat.c}, and put @code{@var{xxx}-nat.o}
+into @code{NATDEPFILES}.
+
+@table @file
+
+@item inftarg.c
+This contains the @emph{target_ops vector} that supports Unix child
+processes on systems which use ptrace and wait to control the child.
+
+@item procfs.c
+This contains the @emph{target_ops vector} that supports Unix child
+processes on systems which use /proc to control the child.
+
+@item fork-child.c
+This does the low-level grunge that uses Unix system calls
+to do a "fork and exec" to start up a child process.
+
+@item infptrace.c
+This is the low level interface to inferior processes for systems
+using the Unix @code{ptrace} call in a vanilla way.
+
+@item coredep.c::fetch_core_registers()
+Support for reading registers out of a core file. This routine calls
+@code{register_addr()}, see below.
+Now that BFD is used to read core files, virtually all machines should
+use @code{coredep.c}, and should just provide @code{fetch_core_registers} in
+@code{@var{xxx}-nat.c} (or @code{REGISTER_U_ADDR} in @code{nm-@var{xxx}.h}).
+
+@item coredep.c::register_addr()
+If your @code{nm-@var{xxx}.h} file defines the macro
+@code{REGISTER_U_ADDR(addr, blockend, regno)}, it should be defined to
+set @code{addr} to the offset within the @samp{user}
+struct of GDB register number @code{regno}. @code{blockend} is the
+offset within the ``upage'' of @code{u.u_ar0}.
+If @code{REGISTER_U_ADDR} is defined,
+@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{xxx}-nat.c} file, and be sure @code{@var{xxx}-nat.o} is in
+the @code{NATDEPFILES} list. If you have your own
+@code{fetch_core_registers()}, you may not need a separate
+@code{register_addr()}. Many custom @code{fetch_core_registers()}
+implementations simply locate the registers themselves.@refill
+@end table
+
+When making GDB run native on a new operating system,
+to make it possible to debug
+core files, you will need to either write specific code for parsing your
+OS's core files, or customize @file{bfd/trad-core.c}. First, use
+whatever @code{#include} files your machine uses to define the struct of
+registers that is accessible (possibly in the u-area) in a core file
+(rather than @file{machine/reg.h}), and an include file that defines whatever
+header exists on a core file (e.g. the u-area or a @samp{struct core}). Then
+modify @code{trad_unix_core_file_p()} to use these values to set up the
+section information for the data segment, stack segment, any other
+segments in the core file (perhaps shared library contents or control
+information), ``registers'' segment, and if there are two discontiguous
+sets of registers (e.g. integer and float), the ``reg2'' segment. This
+section information basically delimits areas in the core file in a
+standard way, which the section-reading routines in BFD know how to seek
+around in.
+
+Then back in GDB, you need a matching routine called
+@code{fetch_core_registers()}. If you can use the generic one, it's in
+@file{coredep.c}; if not, it's in your @file{@var{xxx}-nat.c} file.
+It will be passed a char pointer to the entire ``registers'' segment,
+its length, and a zero; or a char pointer to the entire ``regs2''
+segment, its length, and a 2. The routine should suck out the supplied
+register values and install them into GDB's ``registers'' array.
+(@xref{New Architectures,,Defining a New Host or Target Architecture},
+for more info about this.)
+
+If your system uses @file{/proc} to control processes, and uses ELF
+format core files, then you may be able to use the same routines
+for reading the registers out of processes and out of core files.
+
+@node Target
+@chapter Adding a New Target
+
+For a new target called @var{ttt}, first specify the configuration as
+described in @ref{Config,,Adding a New Configuration}. If your new
+target is the same as your new host, you've probably already done that.
+
+A variety of files specify attributes of the GDB target environment:
+
+@table @file
+@item gdb/config/@var{arch}/@var{ttt}.mt
+Contains a Makefile fragment specific to this target.
+Specifies what object files are needed for target @var{ttt}, by
+defining @samp{TDEPFILES=@dots{}}.
+Also specifies the header file which describes @var{ttt}, by defining
+@samp{TM_FILE= tm-@var{ttt}.h}. You can also define @samp{TM_CFLAGS},
+@samp{TM_CLIBS}, @samp{TM_CDEPS},
+and other Makefile variables here; see @file{Makefile.in}.
+
+@item gdb/config/@var{arch}/tm-@var{ttt}.h
+(@file{tm.h} is a link to this file, created by configure).
+Contains macro definitions about the target machine's
+registers, stack frame format and instructions.
+Crib from existing @file{tm-*.h} files when building a new one.
+
+@item gdb/@var{ttt}-tdep.c
+Contains any miscellaneous code required for this target machine.
+On some machines it doesn't exist at all. Sometimes the macros
+in @file{tm-@var{ttt}.h} become very complicated, so they are
+implemented as functions here instead, and the macro is simply
+defined to call the function.
+
+@item gdb/exec.c
+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
+target should be able to use the generic exec.c rather than its
+own custom code.
+
+@item gdb/@var{arch}-pinsn.c
+Prints (disassembles) the target machine's instructions.
+This file is usually shared with other target machines which use the
+same processor, which is why it is @file{@var{arch}-pinsn.c} rather
+than @file{@var{ttt}-pinsn.c}.
+
+@item gdb/@var{arch}-opcode.h
+Contains some large initialized
+data structures describing the target machine's instructions.
+This is a bit strange for a @file{.h} file, but it's OK since
+it is only included in one place. @file{@var{arch}-opcode.h} is shared
+between the debugger and the assembler, if the GNU assembler has been
+ported to the target machine.
+
+@item gdb/config/@var{arch}/tm-@var{arch}.h
+This often exists to describe the basic layout of the target machine's
+processor chip (registers, stack, etc).
+If used, it is included by @file{tm-@var{xxx}.h}. It can
+be shared among many targets that use the same processor.
+
+@item gdb/@var{arch}-tdep.c
+Similarly, there are often common subroutines that are shared by all
+target machines that use this particular architecture.
+@end table
+
+When adding support for a new target machine, there are various areas
+of support that might need change, or might be OK.
+
+If you are using an existing object file format (a.out or COFF),
+there is probably little to be done. See @file{bfd/doc/bfd.texinfo}
+for more information on writing new a.out or COFF versions.
+
+If you need to add a new object file format, you must first add it to
+BFD. This is beyond the scope of this document right now. Basically
+you must build a transfer vector (of type @code{bfd_target}), which will
+mean writing all the required routines, and add it to the list in
+@file{bfd/targets.c}.
+
+You must then arrange for the BFD code to provide access to the
+debugging symbols. Generally GDB will have to call swapping routines
+from BFD and a few other BFD internal routines to locate the debugging
+information. As much as possible, GDB should not depend on the BFD
+internal data structures.
+
+For some targets (e.g., COFF), there is a special transfer vector used
+to call swapping routines, since the external data structures on various
+platforms have different sizes and layouts. Specialized routines that
+will only ever be implemented by one object file format may be called
+directly. This interface should be described in a file
+@file{bfd/libxxx.h}, which is included by GDB.
+
+If you are adding a new operating system for an existing CPU chip, add a
+@file{tm-@var{xos}.h} file that describes the operating system
+facilities that are unusual (extra symbol table info; the breakpoint
+instruction needed; etc). Then write a
+@file{tm-@var{xarch}-@var{xos}.h} that just @code{#include}s
+@file{tm-@var{xarch}.h} and @file{tm-@var{xos}.h}. (Now that we have
+three-part configuration names, this will probably get revised to
+separate the @var{xos} configuration from the @var{xarch}
+configuration.)
+
+
+@node Languages
+@chapter Adding a Source Language to GDB
+
+To add other languages to GDB's expression parser, follow the following steps:
+
+@table @emph
+@item Create the expression parser.
+
+This should reside in a file @file{@var{lang}-exp.y}. Routines for building
+parsed expressions into a @samp{union exp_element} list are in @file{parse.c}.
+
+Since we can't depend upon everyone having Bison, and YACC produces
+parsers that define a bunch of global names, the following lines
+@emph{must} be included at the top of the YACC parser, to prevent
+the various parsers from defining the same global names:
+
+@example
+#define yyparse @var{lang}_parse
+#define yylex @var{lang}_lex
+#define yyerror @var{lang}_error
+#define yylval @var{lang}_lval
+#define yychar @var{lang}_char
+#define yydebug @var{lang}_debug
+#define yypact @var{lang}_pact
+#define yyr1 @var{lang}_r1
+#define yyr2 @var{lang}_r2
+#define yydef @var{lang}_def
+#define yychk @var{lang}_chk
+#define yypgo @var{lang}_pgo
+#define yyact @var{lang}_act
+#define yyexca @var{lang}_exca
+#define yyerrflag @var{lang}_errflag
+#define yynerrs @var{lang}_nerrs
+@end example
+
+At the bottom of your parser, define a @code{struct language_defn} and
+initialize it with the right values for your language. Define an
+@code{initialize_@var{lang}} routine and have it call
+@samp{add_language(@var{lang}_language_defn)} to tell the rest of GDB
+that your language exists. You'll need some other supporting variables
+and functions, which will be used via pointers from your
+@code{@var{lang}_language_defn}. See the declaration of @code{struct
+language_defn} in @file{language.h}, and the other @file{*-exp.y} files,
+for more information.
+
+@item Add any evaluation routines, if necessary
+
+If you need new opcodes (that represent the operations of the language),
+add them to the enumerated type in @file{expression.h}. Add support
+code for these operations in @code{eval.c:evaluate_subexp()}. Add cases
+for new opcodes in two functions from @file{parse.c}:
+@code{prefixify_subexp()} and @code{length_of_subexp()}. These compute
+the number of @code{exp_element}s that a given operation takes up.
+
+@item Update some existing code
+
+Add an enumerated identifier for your language to the enumerated type
+@code{enum language} in @file{defs.h}.
+
+Update the routines in @file{language.c} so your language is included. These
+routines include type predicates and such, which (in some cases) are
+language dependent. If your language does not appear in the switch
+statement, an error is reported.
+
+Also included in @file{language.c} is the code that updates the variable
+@code{current_language}, and the routines that translate the
+@code{language_@var{lang}} enumerated identifier into a printable
+string.
+
+Update the function @code{_initialize_language} to include your language. This
+function picks the default language upon startup, so is dependent upon
+which languages that GDB is built for.
+
+Update @code{allocate_symtab} in @file{symfile.c} and/or symbol-reading
+code so that the language of each symtab (source file) is set properly.
+This is used to determine the language to use at each stack frame level.
+Currently, the language is set based upon the extension of the source
+file. If the language can be better inferred from the symbol
+information, please set the language of the symtab in the symbol-reading
+code.
+
+Add helper code to @code{expprint.c:print_subexp()} to handle any new
+expression opcodes you have added to @file{expression.h}. Also, add the
+printed representations of your operators to @code{op_print_tab}.
+
+@item Add a place of call
+
+Add a call to @code{@var{lang}_parse()} and @code{@var{lang}_error} in
+@code{parse.c:parse_exp_1()}.
+
+@item Use macros to trim code
+
+The user has the option of building GDB for some or all of the
+languages. If the user decides to build GDB for the language
+@var{lang}, then every file dependent on @file{language.h} will have the
+macro @code{_LANG_@var{lang}} defined in it. Use @code{#ifdef}s to
+leave out large routines that the user won't need if he or she is not
+using your language.
+
+Note that you do not need to do this in your YACC parser, since if GDB
+is not build for @var{lang}, then @file{@var{lang}-exp.tab.o} (the
+compiled form of your parser) is not linked into GDB at all.
+
+See the file @file{configure.in} for how GDB is configured for different
+languages.
+
+@item Edit @file{Makefile.in}
+
+Add dependencies in @file{Makefile.in}. Make sure you update the macro
+variables such as @code{HFILES} and @code{OBJS}, otherwise your code may
+not get linked in, or, worse yet, it may not get @code{tar}red into the
+distribution!
+@end table
+
+
+@node Releases
+@chapter Configuring GDB for Release
+
+From the top level directory (containing @file{gdb}, @file{bfd},
+@file{libiberty}, and so on):
+@example
+make -f Makefile.in gdb.tar.Z
+@end example
+
+This will properly configure, clean, rebuild any files that are
+distributed pre-built (e.g. @file{c-exp.tab.c} or @file{refcard.ps}),
+and will then make a tarfile. (If the top level directory has already
+beenn configured, you can just do @code{make gdb.tar.Z} instead.)
+
+This procedure requires:
+@itemize @bullet
+@item symbolic links
+@item @code{makeinfo} (texinfo2 level)
+@item @TeX{}
+@item @code{dvips}
+@item @code{yacc} or @code{bison}
+@end itemize
+@noindent
+@dots{} and the usual slew of utilities (@code{sed}, @code{tar}, etc.).
+
+@subheading TEMPORARY RELEASE PROCEDURE FOR DOCUMENTATION
+
+@file{gdb.texinfo} is currently marked up using the texinfo-2 macros,
+which are not yet a default for anything (but we have to start using
+them sometime).
+
+For making paper, the only thing this implies is the right generation of
+@file{texinfo.tex} needs to be included in the distribution.
+
+For making info files, however, rather than duplicating the texinfo2
+distribution, generate @file{gdb-all.texinfo} locally, and include the files
+@file{gdb.info*} in the distribution. Note the plural; @code{makeinfo} will
+split the document into one overall file and five or so included files.
+
+
+@node Partial Symbol Tables
+@chapter Partial Symbol Tables
+
+GDB has three types of symbol tables.
+
+@itemize @bullet
+@item full symbol tables (symtabs). These contain the main
+information about symbols and addresses.
+@item partial symbol tables (psymtabs). These contain enough
+information to know when to read the corresponding
+part of the full symbol table.
+@item minimal symbol tables (msymtabs). These contain information
+gleaned from non-debugging symbols.
+@end itemize
+
+This section describes partial symbol tables.
+
+A psymtab is constructed by doing a very quick pass over an executable
+file's debugging information. Small amounts of information are
+extracted -- enough to identify which parts of the symbol table will
+need to be re-read and fully digested later, when the user needs the
+information. The speed of this pass causes GDB to start up very
+quickly. Later, as the detailed rereading occurs, it occurs in small
+pieces, at various times, and the delay therefrom is mostly invisible to
+the user. (@xref{Symbol Reading}.)
+
+The symbols that show up in a file's psymtab should be, roughly, those
+visible to the debugger's user when the program is not running code from
+that file. These include external symbols and types, static
+symbols and types, and enum values declared at file scope.
+
+The psymtab also contains the range of instruction addresses that the
+full symbol table would represent.
+
+The idea is that there are only two ways for the user (or much of
+the code in the debugger) to reference a symbol:
+
+@itemize @bullet
+
+@item by its address
+(e.g. execution stops at some address which is inside a function
+in this file). The address will be noticed to be in the
+range of this psymtab, and the full symtab will be read in.
+@code{find_pc_function}, @code{find_pc_line}, and other @code{find_pc_@dots{}}
+functions handle this.
+
+@item by its name
+(e.g. the user asks to print a variable, or set a breakpoint on a
+function). Global names and file-scope names will be found in the
+psymtab, which will cause the symtab to be pulled in. Local names will
+have to be qualified by a global name, or a file-scope name, in which
+case we will have already read in the symtab as we evaluated the
+qualifier. Or, a local symbol can be referenced when
+we are "in" a local scope, in which case the first case applies.
+@code{lookup_symbol} does most of the work here.
+
+@end itemize
+
+The only reason that psymtabs exist is to cause a symtab to be read in
+at the right moment. Any symbol that can be elided from a psymtab,
+while still causing that to happen, should not appear in it. Since
+psymtabs don't have the idea of scope, you can't put local symbols in
+them anyway. Psymtabs don't have the idea of the type of a symbol,
+either, so types need not appear, unless they will be referenced by
+name.
+
+It is a bug for GDB to behave one way when only a psymtab has been read,
+and another way if the corresponding symtab has been read in. Such
+bugs are typically caused by a psymtab that does not contain all the
+visible symbols, or which has the wrong instruction address ranges.
+
+The psymtab for a particular section of a symbol-file (objfile)
+could be thrown away after the symtab has been read in. The symtab
+should always be searched before the psymtab, so the psymtab will
+never be used (in a bug-free environment). Currently,
+psymtabs are allocated on an obstack, and all the psymbols themselves
+are allocated in a pair of large arrays on an obstack, so there is
+little to be gained by trying to free them unless you want to do a lot
+more work.
+
+@node Types
+@chapter Types
+
+Fundamental Types (e.g., FT_VOID, FT_BOOLEAN).
+
+These are the fundamental types that gdb uses internally. Fundamental
+types from the various debugging formats (stabs, ELF, etc) are mapped into
+one of these. They are basically a union of all fundamental types that
+gdb knows about for all the languages that gdb knows about.
+
+Type Codes (e.g., TYPE_CODE_PTR, TYPE_CODE_ARRAY).
+
+Each time gdb builds an internal type, it marks it with one of these
+types. The type may be a fundamental type, such as TYPE_CODE_INT, or
+a derived type, such as TYPE_CODE_PTR which is a pointer to another
+type. Typically, several FT_* types map to one TYPE_CODE_* type, and
+are distinguished by other members of the type struct, such as whether
+the type is signed or unsigned, and how many bits it uses.
+
+Builtin Types (e.g., builtin_type_void, builtin_type_char).
+
+These are instances of type structs that roughly correspond to fundamental
+types and are created as global types for gdb to use for various ugly
+historical reasons. We eventually want to eliminate these. Note for
+example that builtin_type_int initialized in gdbtypes.c is basically the
+same as a TYPE_CODE_INT type that is initialized in c-lang.c for an
+FT_INTEGER fundamental type. The difference is that the builtin_type is
+not associated with any particular objfile, and only one instance exists,
+while c-lang.c builds as many TYPE_CODE_INT types as needed, with each
+one associated with some particular objfile.
+
+@node BFD support for GDB
+@chapter Binary File Descriptor Library Support for GDB
+
+BFD provides support for GDB in several ways:
+
+@table @emph
+@item identifying executable and core files
+BFD will identify a variety of file types, including a.out, coff, and
+several variants thereof, as well as several kinds of core files.
+
+@item access to sections of files
+BFD parses the file headers to determine the names, virtual addresses,
+sizes, and file locations of all the various named sections in files
+(such as the text section or the data section). GDB simply calls
+BFD to read or write section X at byte offset Y for length Z.
+
+@item specialized core file support
+BFD provides routines to determine the failing command name stored
+in a core file, the signal with which the program failed, and whether
+a core file matches (i.e. could be a core dump of) a particular executable
+file.
+
+@item locating the symbol information
+GDB uses an internal interface of BFD to determine where to find the
+symbol information in an executable file or symbol-file. GDB itself
+handles the reading of symbols, since BFD does not ``understand'' debug
+symbols, but GDB uses BFD's cached information to find the symbols,
+string table, etc.
+@end table
+
+@c The interface for symbol reading is described in @ref{Symbol
+@c Reading,,Symbol Reading}.
+
+
+@node Symbol Reading
+@chapter Symbol Reading
+
+GDB reads symbols from "symbol files". The usual symbol file is the
+file containing the program which gdb is debugging. GDB can be directed
+to use a different file for symbols (with the ``symbol-file''
+command), and it can also read more symbols via the ``add-file'' and ``load''
+commands, or while reading symbols from shared libraries.
+
+Symbol files are initially opened by @file{symfile.c} using the BFD
+library. BFD identifies the type of the file by examining its header.
+@code{symfile_init} then uses this identification to locate a
+set of symbol-reading functions.
+
+Symbol reading modules identify themselves to GDB by calling
+@code{add_symtab_fns} during their module initialization. The argument
+to @code{add_symtab_fns} is a @code{struct sym_fns} which contains
+the name (or name prefix) of the symbol format, the length of the prefix,
+and pointers to four functions. These functions are called at various
+times to process symbol-files whose identification matches the specified
+prefix.
+
+The functions supplied by each module are:
+
+@table @code
+@item @var{xxx}_symfile_init(struct sym_fns *sf)
+
+Called from @code{symbol_file_add} when we are about to read a new
+symbol file. This function should clean up any internal state
+(possibly resulting from half-read previous files, for example)
+and prepare to read a new symbol file. Note that the symbol file
+which we are reading might be a new "main" symbol file, or might
+be a secondary symbol file whose symbols are being added to the
+existing symbol table.
+
+The argument to @code{@var{xxx}_symfile_init} is a newly allocated
+@code{struct sym_fns} whose @code{bfd} field contains the BFD
+for the new symbol file being read. Its @code{private} field
+has been zeroed, and can be modified as desired. Typically,
+a struct of private information will be @code{malloc}'d, and
+a pointer to it will be placed in the @code{private} field.
+
+There is no result from @code{@var{xxx}_symfile_init}, but it can call
+@code{error} if it detects an unavoidable problem.
+
+@item @var{xxx}_new_init()
+
+Called from @code{symbol_file_add} when discarding existing symbols.
+This function need only handle
+the symbol-reading module's internal state; the symbol table data
+structures visible to the rest of GDB will be discarded by
+@code{symbol_file_add}. It has no arguments and no result.
+It may be called after @code{@var{xxx}_symfile_init}, if a new symbol
+table is being read, or may be called alone if all symbols are
+simply being discarded.
+
+@item @var{xxx}_symfile_read(struct sym_fns *sf, CORE_ADDR addr, int mainline)
+
+Called from @code{symbol_file_add} to actually read the symbols from a
+symbol-file into a set of psymtabs or symtabs.
+
+@code{sf} points to the struct sym_fns originally passed to
+@code{@var{xxx}_sym_init} for possible initialization. @code{addr} is the
+offset between the file's specified start address and its true address
+in memory. @code{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.@refill
+@end table
+
+In addition, if a symbol-reading module creates psymtabs when
+@var{xxx}_symfile_read is called, these psymtabs will contain a pointer to
+a function @code{@var{xxx}_psymtab_to_symtab}, which can be called from
+any point in the GDB symbol-handling code.
+
+@table @code
+@item @var{xxx}_psymtab_to_symtab (struct partial_symtab *pst)
+
+Called from @code{psymtab_to_symtab} (or the PSYMTAB_TO_SYMTAB
+macro) if the psymtab has not already been read in and had its
+@code{pst->symtab} pointer set. The argument is the psymtab
+to be fleshed-out into a symtab. Upon return, pst->readin
+should have been set to 1, and pst->symtab should contain a
+pointer to the new corresponding symtab, or zero if there
+were no symbols in that part of the symbol file.
+@end table
+
+
+@node Cleanups
+@chapter Cleanups
+
+Cleanups are a structured way to deal with things that need to be done
+later. When your code does something (like @code{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 struct cleanup *@var{old_chain};
+Declare a variable which will hold a cleanup chain handle.
+
+@item @var{old_chain} = make_cleanup (@var{function}, @var{arg});
+Make a cleanup which will cause @var{function} to be called with @var{arg}
+(a @code{char *}) later. The result, @var{old_chain}, is a handle that can be
+passed to @code{do_cleanups} or @code{discard_cleanups} later. Unless you are
+going to call @code{do_cleanups} or @code{discard_cleanups} yourself,
+you can ignore the result from @code{make_cleanup}.
+
+
+@item do_cleanups (@var{old_chain});
+Perform all cleanups done since @code{make_cleanup} returned @var{old_chain}.
+E.g.:
+@example
+make_cleanup (a, 0);
+old = make_cleanup (b, 0);
+do_cleanups (old);
+@end example
+@noindent
+will call @code{b()} but will not call @code{a()}. The cleanup that calls @code{a()} will remain
+in the cleanup chain, and will be done later unless otherwise discarded.@refill
+
+@item discard_cleanups (@var{old_chain});
+Same as @code{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
+@chapter Wrapping Output Lines
+
+Output that goes through @code{printf_filtered} or @code{fputs_filtered} or
+@code{fputs_demangled} needs only to have calls to @code{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 @code{wrap_here} is an indentation string which is printed
+@emph{only} if the line breaks there. This argument is saved away and used
+later. It must remain valid until the next call to @code{wrap_here} or
+until a newline has been printed through the @code{*_filtered} functions.
+Don't pass in a local variable and then return!
+
+It is usually best to call @code{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 (``@code{printf}'') output. Symbol reading routines that print
+warnings are a good example.
+
+
+@node Frames
+@chapter Frames
+
+A frame is a construct that GDB uses to keep track of calling and called
+functions.
+
+@table @code
+@item FRAME_FP
+in the machine description has no meaning to the machine-independent
+part of GDB, except that it is used when setting up a new frame from
+scratch, as follows:
+
+@example
+ create_new_frame (read_register (FP_REGNUM), read_pc ()));
+@end example
+
+Other than that, all the meaning imparted to @code{FP_REGNUM} is imparted by
+the machine-dependent code. So, @code{FP_REGNUM} can have any value that
+is convenient for the code that creates new frames. (@code{create_new_frame}
+calls @code{INIT_EXTRA_FRAME_INFO} if it is defined; that is where you should
+use the @code{FP_REGNUM} value, if your frames are nonstandard.)
+
+@item FRAME_CHAIN
+Given a GDB frame, determine the address of the calling function's
+frame. This will be used to create a new GDB frame struct, and then
+@code{INIT_EXTRA_FRAME_INFO} and @code{INIT_FRAME_PC} will be called for
+the new frame.
+@end table
+
+@node Remote Stubs
+@chapter Remote Stubs
+
+GDB's file @file{remote.c} talks a serial protocol to code that runs
+in the target system. GDB provides several sample ``stubs'' that can
+be integrated into target programs or operating systems for this purpose;
+they are named @file{*-stub.c}.
+
+The GDB user's manual describes how to put such a stub into your target
+code. What follows is a discussion of integrating the SPARC stub
+into a complicated operating system (rather than a simple program),
+by Stu Grossman, the author of this stub.
+
+The trap handling code in the stub assumes the following upon entry to
+trap_low:
+
+@enumerate
+@item %l1 and %l2 contain pc and npc respectively at the time of the trap
+@item traps are disabled
+@item you are in the correct trap window
+@end enumerate
+
+As long as your trap handler can guarantee those conditions, then there is no
+reason why you shouldn't be able to `share' traps with the stub. The stub has
+no requirement that it be jumped to directly from the hardware trap vector.
+That is why it calls @code{exceptionHandler()}, which is provided by the external
+environment. For instance, this could setup the hardware traps to actually
+execute code which calls the stub first, and then transfers to its own trap
+handler.
+
+For the most point, there probably won't be much of an issue with `sharing'
+traps, as the traps we use are usually not used by the kernel, and often
+indicate unrecoverable error conditions. Anyway, this is all controlled by a
+table, and is trivial to modify.
+The most important trap for us is for @code{ta 1}. Without that, we
+can't single step or do breakpoints. Everything else is unnecessary
+for the proper operation of the debugger/stub.
+
+From reading the stub, it's probably not obvious how breakpoints work. They
+are simply done by deposit/examine operations from GDB.
+
+@node Longjmp Support
+@chapter Longjmp Support
+
+GDB has support for figuring out that the target is doing a
+@code{longjmp} and for stopping at the target of the jump, if we are
+stepping. This is done with a few specialized internal breakpoints,
+which are visible in the @code{maint info breakpoint} command.
+
+To make this work, you need to define a macro called
+@code{GET_LONGJMP_TARGET}, which will examine the @code{jmp_buf}
+structure and extract the longjmp target address. Since @code{jmp_buf}
+is target specific, you will need to define it in the appropriate
+@file{tm-xxx.h} file. Look in @file{tm-sun4os4.h} and
+@file{sparc-tdep.c} for examples of how to do this.
+
+@node Coding Style
+@chapter Coding Style
+
+GDB is generally written using the GNU coding standards, as described in
+@file{standards.texi}, which is available for anonymous FTP from GNU
+archive sites. There are some additional considerations for GDB
+maintainers that reflect the unique environment and style of GDB
+maintenance. If you follow these guidelines, GDB will be more
+consistent and easier to maintain.
+
+GDB's policy on the use of prototypes is that prototypes are used
+to @emph{declare} functions but never to @emph{define} them. Simple
+macros are used in the declarations, so that a non-ANSI compiler can
+compile GDB without trouble. The simple macro calls are used like
+this:
+
+@example @code
+extern int
+memory_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+@end example
+
+Note the double parentheses around the parameter types. This allows
+an arbitrary number of parameters to be described, without freaking
+out the C preprocessor. When the function has no parameters, it
+should be described like:
+
+@example @code
+void
+noprocess PARAMS ((void));
+@end example
+
+The @code{PARAMS} macro expands to its argument in ANSI C, or to a simple
+@code{()} in traditional C.
+
+All external functions should have a @code{PARAMS} declaration in a
+header file that callers include. All static functions should have such
+a declaration near the top of their source file.
+
+We don't have a gcc option that will properly check that these rules
+have been followed, but it's GDB policy, and we periodically check it
+using the tools available (plus manual labor), and clean up any remnants.
+
+@node Clean Design
+@chapter Clean Design
+
+In addition to getting the syntax right, there's the little question of
+semantics. Some things are done in certain ways in GDB because long
+experience has shown that the more obvious ways caused various kinds of
+trouble. In particular:
+
+@table @bullet
+@item
+You can't assume the byte order of anything that comes from a
+target (including @var{value}s, object files, and instructions). Such
+things must be byte-swapped using @code{SWAP_TARGET_AND_HOST} in GDB,
+or one of the swap routines defined in @file{bfd.h}, such as @code{bfd_get_32}.
+
+@item
+You can't assume that you know what interface is being used to talk to
+the target system. All references to the target must go through the
+current @code{target_ops} vector.
+
+@item
+You can't assume that the host and target machines are the same machine
+(except in the ``native'' support modules).
+In particular, you can't assume that the target machine's header files
+will be available on the host machine. Target code must bring along its
+own header files -- written from scratch or explicitly donated by their
+owner, to avoid copyright problems.
+
+@item
+Insertion of new @code{#ifdef}'s will be frowned upon. It's much better
+to write the code portably than to conditionalize it for various systems.
+
+@item
+New @code{#ifdef}'s which test for specific compilers or manufacturers
+or operating systems are unacceptable. All @code{#ifdef}'s should test
+for features. The information about which configurations contain which
+features should be segregated into the configuration files. Experience
+has proven far too often that a feature unique to one particular system
+often creeps into other systems; and that a conditional based on
+some predefined macro for your current system will become worthless
+over time, as new versions of your system come out that behave differently
+with regard to this feature.
+
+@item
+Adding code that handles specific architectures, operating systems, target
+interfaces, or hosts, is not acceptable in generic code. If a hook
+is needed at that point, invent a generic hook and define it for your
+configuration, with something like:
+
+@example
+#ifdef WRANGLE_SIGNALS
+ WRANGLE_SIGNALS (signo);
+#endif
+@end example
+
+In your host, target, or native configuration file, as appropriate,
+define @code{WRANGLE_SIGNALS} to do the machine-dependent thing. Take
+a bit of care in defining the hook, so that it can be used by other
+ports in the future, if they need a hook in the same place.
+
+If the hook is not defined, the code should do whatever "most" machines
+want. Using @code{#ifdef}, as above, is the preferred way to do this,
+but sometimes that gets convoluted, in which case use
+
+@example
+#ifndef SPECIAL_FOO_HANDLING
+#define SPECIAL_FOO_HANDLING(pc, sp) (0)
+#endif
+@end example
+
+where the macro is used or in an appropriate header file.
+
+Whether to include a @dfn{small} hook, a hook around the exact pieces of
+code which are system-dependent, or whether to replace a whole function
+with a hook depends on the case. A good example of this dilemma can be
+found in @code{get_saved_register}. All machines that GDB 2.8 ran on
+just needed the @code{FRAME_FIND_SAVED_REGS} hook to find the saved
+registers. Then the SPARC and Pyramid came along, and
+@code{HAVE_REGISTER_WINDOWS} and @code{REGISTER_IN_WINDOW_P} were
+introduced. Then the 29k and 88k required the @code{GET_SAVED_REGISTER}
+hook. The first three are examples of small hooks; the latter replaces
+a whole function. In this specific case, it is useful to have both
+kinds; it would be a bad idea to replace all the uses of the small hooks
+with @code{GET_SAVED_REGISTER}, since that would result in much
+duplicated code. Other times, duplicating a few lines of code here or
+there is much cleaner than introducing a large number of small hooks.
+
+Another way to generalize GDB along a particular interface is with an
+attribute struct. For example, GDB has been generalized to handle
+multiple kinds of remote interfaces -- not by #ifdef's everywhere, but
+by defining the "target_ops" structure and having a current target (as
+well as a stack of targets below it, for memory references). Whenever
+something needs to be done that depends on which remote interface we are
+using, a flag in the current target_ops structure is tested (e.g.
+`target_has_stack'), or a function is called through a pointer in the
+current target_ops structure. In this way, when a new remote interface
+is added, only one module needs to be touched -- the one that actually
+implements the new remote interface. Other examples of
+attribute-structs are BFD access to multiple kinds of object file
+formats, or GDB's access to multiple source languages.
+
+Please avoid duplicating code. For example, in GDB 3.x all the code
+interfacing between @code{ptrace} and the rest of GDB was duplicated in
+@file{*-dep.c}, and so changing something was very painful. In GDB 4.x,
+these have all been consolidated into @file{infptrace.c}.
+@file{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.
+
+@item
+@emph{Do} write code that doesn't depend on the sizes of C data types,
+the format of the host's floating point numbers, the alignment of anything,
+or the order of evaluation of expressions. In short, follow good
+programming practices for writing portable C code.
+
+@end table
+
+@node Submitting Patches
+@chapter Submitting Patches
+
+Thanks for thinking of offering your changes back to the community of
+GDB users. In general we like to get well designed enhancements.
+Thanks also for checking in advance about the best way to transfer the
+changes.
+
+The two main problems with getting your patches in are,
+
+@table @bullet
+@item
+The GDB maintainers will only install ``cleanly designed'' patches.
+You may not always agree on what is clean design.
+@pxref{Coding Style}, @pxref{Clean Design}.
+
+@item
+If the maintainers don't have time to put the patch in when it
+arrives, or if there is any question about a patch, it
+goes into a large queue with everyone else's patches and
+bug reports.
+@end table
+
+I don't know how to get past these problems except by continuing to try.
+
+There are two issues here -- technical and legal.
+
+The legal issue is that to incorporate substantial changes requires a
+copyright assignment from you and/or your employer, granting ownership
+of the changes to the Free Software Foundation. You can get the
+standard document for doing this by sending mail to
+@code{gnu@@prep.ai.mit.edu} and asking for it. I recommend that people
+write in "All programs owned by the Free Software Foundation" as "NAME
+OF PROGRAM", so that changes in many programs (not just GDB, but GAS,
+Emacs, GCC, etc) can be contributed with only one piece of legalese
+pushed through the bureacracy and filed with the FSF. I can't start
+merging changes until this paperwork is received by the FSF (their
+rules, which I follow since I maintain it for them).
+
+Technically, the easiest way to receive changes is to receive each
+feature as a small context diff or unidiff, suitable for "patch".
+Each message sent to me should include the changes to C code and
+header files for a single feature, plus ChangeLog entries for each
+directory where files were modified, and diffs for any changes needed
+to the manuals (gdb/doc/gdb.texi or gdb/doc/gdbint.texi). If there
+are a lot of changes for a single feature, they can be split down
+into multiple messages.
+
+In this way, if I read and like the feature, I can add it to the
+sources with a single patch command, do some testing, and check it in.
+If you leave out the ChangeLog, I have to write one. If you leave
+out the doc, I have to puzzle out what needs documenting. Etc.
+
+The reason to send each change in a separate message is that I will
+not install some of the changes. They'll be returned to you with
+questions or comments. If I'm doing my job, my message back to you
+will say what you have to fix in order to make the change acceptable.
+The reason to have separate messages for separate features is so
+that other changes (which I @emph{am} willing to accept) can be installed
+while one or more changes are being reworked. If multiple features
+are sent in a single message, I tend to not put in the effort to sort
+out the acceptable changes from the unacceptable, so none of the
+features get installed until all are acceptable.
+
+If this sounds painful or authoritarian, well, it is. But I get a lot
+of bug reports and a lot of patches, and most of them don't get
+installed because I don't have the time to finish the job that the bug
+reporter or the contributor could have done. Patches that arrive
+complete, working, and well designed, tend to get installed on the day
+they arrive. The others go into a queue and get installed if and when
+I scan back over the queue -- which can literally take months
+sometimes. It's in both our interests to make patch installation easy
+-- you get your changes installed, and I make some forward progress on
+GDB in a normal 12-hour day (instead of them having to wait until I
+have a 14-hour or 16-hour day to spend cleaning up patches before I
+can install them).
+
+Please send patches to @code{bug-gdb@@prep.ai.mit.edu}, if they are less
+than about 25,000 characters. If longer than that, either make them
+available somehow (e.g. anonymous FTP), and announce it on
+@code{bug-gdb}, or send them directly to the GDB maintainers at
+@code{gdb-patches@@cygnus.com}.
+
+@node Host Conditionals
+@chapter Host Conditionals
+
+When GDB is configured and compiled, various macros are defined or left
+undefined, to control compilation based on the attributes of the host
+system. These macros and their meanings are:
+
+@emph{NOTE: For now, both host and target conditionals are here.
+Eliminate target conditionals from this list as they are identified.}
+
+@table @code
+@item BLOCK_ADDRESS_FUNCTION_RELATIVE
+dbxread.c
+@item GDBINIT_FILENAME
+The default name of GDB's initialization file (normally @file{.gdbinit}).
+@item KERNELDEBUG
+tm-hppa.h
+@item MEM_FNS_DECLARED
+Your host config file defines this if it includes
+declarations of @code{memcpy} and @code{memset}. Define this
+to avoid conflicts between the native include
+files and the declarations in @file{defs.h}.
+@item NO_SYS_FILE
+dbxread.c
+@item PYRAMID_CONTROL_FRAME_DEBUGGING
+pyr-xdep.c
+@item SIGWINCH_HANDLER_BODY
+utils.c
+@item ADDITIONAL_OPTIONS
+main.c
+@item ADDITIONAL_OPTION_CASES
+main.c
+@item ADDITIONAL_OPTION_HANDLER
+main.c
+@item ADDITIONAL_OPTION_HELP
+main.c
+@item ADDR_BITS_REMOVE
+defs.h
+@item AIX_BUGGY_PTRACE_CONTINUE
+infptrace.c
+@item ALIGN_STACK_ON_STARTUP
+main.c
+@item ALTOS
+altos-xdep.c
+@item ALTOS_AS
+xm-altos.h
+@item ASCII_COFF
+remote-adapt.c
+@item BADMAG
+coffread.c
+@item BCS
+tm-delta88.h
+@item BEFORE_MAIN_LOOP_HOOK
+main.c
+@item BELIEVE_PCC_PROMOTION
+coffread.c
+@item BELIEVE_PCC_PROMOTION_TYPE
+stabsread.c
+@item BITS_BIG_ENDIAN
+defs.h
+@item BKPT_AT_MAIN
+solib.c
+@item BLOCK_ADDRESS_ABSOLUTE
+dbxread.c
+@item BPT_VECTOR
+tm-m68k.h
+@item BREAKPOINT
+tm-m68k.h
+@item BREAKPOINT_DEBUG
+breakpoint.c
+@item BROKEN_LARGE_ALLOCA
+Avoid large @code{alloca}'s. For example, on sun's, Large alloca's fail
+because the attempt to increase the stack limit in main() fails because
+shared libraries are allocated just below the initial stack limit. The
+SunOS kernel will not allow the stack to grow into the area occupied by
+the shared libraries.
+@item BSTRING
+regex.c
+@item CALL_DUMMY
+valops.c
+@item CALL_DUMMY_LOCATION
+inferior.h
+@item CALL_DUMMY_STACK_ADJUST
+valops.c
+@item CANNOT_FETCH_REGISTER
+hppabsd-xdep.c
+@item CANNOT_STORE_REGISTER
+findvar.c
+@item CFRONT_PRODUCER
+dwarfread.c
+@item CHILD_PREPARE_TO_STORE
+inftarg.c
+@item CLEAR_DEFERRED_STORES
+inflow.c
+@item CLEAR_SOLIB
+objfiles.c
+@item COFF_ENCAPSULATE
+hppabsd-tdep.c
+@item COFF_FORMAT
+symm-tdep.c
+@item CORE_NEEDS_RELOCATION
+stack.c
+@item CPLUS_MARKER
+cplus-dem.c
+@item CREATE_INFERIOR_HOOK
+infrun.c
+@item C_ALLOCA
+regex.c
+@item C_GLBLREG
+coffread.c
+@item DBXREAD_ONLY
+partial-stab.h
+@item DBX_PARM_SYMBOL_CLASS
+stabsread.c
+@item DEBUG
+remote-adapt.c
+@item DEBUG_INFO
+partial-stab.h
+@item DEBUG_PTRACE
+hppabsd-xdep.c
+@item DECR_PC_AFTER_BREAK
+breakpoint.c
+@item DEFAULT_PROMPT
+The default value of the prompt string (normally @code{"(gdb) "}).
+@item DELTA88
+m88k-xdep.c
+@item DEV_TTY
+symmisc.c
+@item DGUX
+m88k-xdep.c
+@item DISABLE_UNSETTABLE_BREAK
+breakpoint.c
+@item DONT_USE_REMOTE
+remote.c
+@item DO_DEFERRED_STORES
+infrun.c
+@item DO_REGISTERS_INFO
+infcmd.c
+@item EXTRACT_RETURN_VALUE
+tm-m68k.h
+@item EXTRACT_STRUCT_VALUE_ADDRESS
+values.c
+@item EXTRA_FRAME_INFO
+frame.h
+@item EXTRA_SYMTAB_INFO
+symtab.h
+@item FILES_INFO_HOOK
+target.c
+@item FLOAT_INFO
+infcmd.c
+@item FOPEN_RB
+defs.h
+@item FRAMELESS_FUNCTION_INVOCATION
+blockframe.c
+@item FRAME_ARGS_ADDRESS_CORRECT
+stack.c
+@item FRAME_CHAIN_COMBINE
+blockframe.c
+@item FRAME_CHAIN_VALID
+frame.h
+@item FRAME_CHAIN_VALID_ALTERNATE
+frame.h
+@item FRAME_FIND_SAVED_REGS
+stack.c
+@item FRAME_GET_BASEREG_VALUE
+frame.h
+@item FRAME_NUM_ARGS
+tm-m68k.h
+@item FRAME_SPECIFICATION_DYADIC
+stack.c
+@item FUNCTION_EPILOGUE_SIZE
+coffread.c
+@item F_OK
+xm-ultra3.h
+@item GCC2_COMPILED_FLAG_SYMBOL
+dbxread.c
+@item GCC_COMPILED_FLAG_SYMBOL
+dbxread.c
+@item GCC_MANGLE_BUG
+symtab.c
+@item GCC_PRODUCER
+dwarfread.c
+@item GET_SAVED_REGISTER
+findvar.c
+@item GPLUS_PRODUCER
+dwarfread.c
+@item HANDLE_RBRAC
+partial-stab.h
+@item HAVE_MMAP
+In some cases, use the system call @code{mmap} for reading symbol
+tables. For some machines this allows for sharing and quick updates.
+@item HAVE_REGISTER_WINDOWS
+findvar.c
+@item HAVE_SIGSETMASK
+main.c
+@item HAVE_TERMIO
+inflow.c
+@item HEADER_SEEK_FD
+arm-tdep.c
+@item HOSTING_ONLY
+xm-rtbsd.h
+@item HOST_BYTE_ORDER
+ieee-float.c
+@item HPUX_ASM
+xm-hp300hpux.h
+@item HPUX_VERSION_5
+hp300ux-xdep.c
+@item HP_OS_BUG
+infrun.c
+@item I80960
+remote-vx.c
+@item IEEE_DEBUG
+ieee-float.c
+@item IEEE_FLOAT
+valprint.c
+@item IGNORE_SYMBOL
+dbxread.c
+@item INIT_EXTRA_FRAME_INFO
+blockframe.c
+@item INIT_EXTRA_SYMTAB_INFO
+symfile.c
+@item INIT_FRAME_PC
+blockframe.c
+@item INNER_THAN
+valops.c
+@item INT_MAX
+defs.h
+@item INT_MIN
+defs.h
+@item IN_GDB
+i960-pinsn.c
+@item IN_SIGTRAMP
+infrun.c
+@item IN_SOLIB_TRAMPOLINE
+infrun.c
+@item ISATTY
+main.c
+@item IS_TRAPPED_INTERNALVAR
+values.c
+@item KERNELDEBUG
+dbxread.c
+@item KERNEL_DEBUGGING
+tm-ultra3.h
+@item KERNEL_U_ADDR
+Define this to the address of the @code{u} structure (the ``user struct'',
+also known as the ``u-page'') in kernel virtual memory. GDB needs to know
+this so that it can subtract this address from absolute addresses in
+the upage, that are obtained via ptrace or from core files. On systems
+that don't need this value, set it to zero.
+@item KERNEL_U_ADDR_BSD
+Define this to cause GDB to determine the address of @code{u} at runtime,
+by using Berkeley-style @code{nlist} on the kernel's image in the root
+directory.
+@item KERNEL_U_ADDR_HPUX
+Define this to cause GDB to determine the address of @code{u} at runtime,
+by using HP-style @code{nlist} on the kernel's image in the root
+directory.
+@item LCC_PRODUCER
+dwarfread.c
+@item LOG_FILE
+remote-adapt.c
+@item LONGERNAMES
+cplus-dem.c
+@item LONGEST
+defs.h
+@item CC_HAS_LONG_LONG
+defs.h
+@item PRINTF_HAS_LONG_LONG
+defs.h
+@item LONG_MAX
+defs.h
+@item LSEEK_NOT_LINEAR
+source.c
+@item L_LNNO32
+coffread.c
+@item L_SET
+This macro is used as the argument to lseek (or, most commonly, bfd_seek).
+FIXME, it should be replaced by SEEK_SET instead, which is the POSIX equivalent.
+@item MACHKERNELDEBUG
+hppabsd-tdep.c
+@item MAINTENANCE
+dwarfread.c
+@item MAINTENANCE_CMDS
+If the value of this is 1, then a number of optional maintenance commands
+are compiled in.
+@item MALLOC_INCOMPATIBLE
+Define this if the system's prototype for @code{malloc} differs from the
+@sc{ANSI} definition.
+@item MIPSEL
+mips-tdep.c
+@item MMAP_BASE_ADDRESS
+When using HAVE_MMAP, the first mapping should go at this address.
+@item MMAP_INCREMENT
+when using HAVE_MMAP, this is the increment between mappings.
+@item MONO
+ser-go32.c
+@item MOTOROLA
+xm-altos.h
+@item NBPG
+altos-xdep.c
+@item NEED_POSIX_SETPGID
+infrun.c
+@item NEED_TEXT_START_END
+exec.c
+@item NFAILURES
+regex.c
+@item NORETURN
+(in defs.h - is this really useful to define/undefine?)
+@item NOTDEF
+regex.c
+@item NOTDEF
+remote-adapt.c
+@item NOTDEF
+remote-mm.c
+@item NOTICE_SIGNAL_HANDLING_CHANGE
+infrun.c
+@item NO_HIF_SUPPORT
+remote-mm.c
+@item NO_JOB_CONTROL
+signals.h
+@item NO_MMALLOC
+GDB will use the @code{mmalloc} library for memory allocation for symbol
+reading, unless this symbol is defined. Define it on systems
+on which @code{mmalloc} does not
+work for some reason. One example is the DECstation, where its RPC
+library can't cope with our redefinition of @code{malloc} to call
+@code{mmalloc}. When defining @code{NO_MMALLOC}, you will also have
+to override the setting of @code{MMALLOC_LIB} to empty, in the Makefile.
+Therefore, this define is usually set on the command line by overriding
+@code{MMALLOC_DISABLE} in @file{config/*/*.mh}, rather than by defining
+it in @file{xm-*.h}.
+@item NO_MMALLOC_CHECK
+Define this if you are using @code{mmalloc}, but don't want the overhead
+of checking the heap with @code{mmcheck}.
+@item NO_SIGINTERRUPT
+remote-adapt.c
+@item NO_SINGLE_STEP
+infptrace.c
+@item NS32K_SVC_IMMED_OPERANDS
+ns32k-opcode.h
+@item NUMERIC_REG_NAMES
+mips-tdep.c
+@item N_SETV
+dbxread.c
+@item N_SET_MAGIC
+hppabsd-tdep.c
+@item NaN
+tm-umax.h
+@item ONE_PROCESS_WRITETEXT
+breakpoint.c
+@item O_BINARY
+exec.c
+@item O_RDONLY
+xm-ultra3.h
+@item PC
+convx-opcode.h
+@item PCC_SOL_BROKEN
+dbxread.c
+@item PC_IN_CALL_DUMMY
+inferior.h
+@item PC_LOAD_SEGMENT
+stack.c
+@item PRINT_RANDOM_SIGNAL
+infcmd.c
+@item PRINT_REGISTER_HOOK
+infcmd.c
+@item PRINT_TYPELESS_INTEGER
+valprint.c
+@item PROCESS_LINENUMBER_HOOK
+buildsym.c
+@item PROLOGUE_FIRSTLINE_OVERLAP
+infrun.c
+@item PSIGNAL_IN_SIGNAL_H
+defs.h
+@item PUSH_ARGUMENTS
+valops.c
+@item PYRAMID_CONTROL_FRAME_DEBUGGING
+pyr-xdep.c
+@item PYRAMID_CORE
+pyr-xdep.c
+@item PYRAMID_PTRACE
+pyr-xdep.c
+@item REGISTER_BYTES
+remote.c
+@item REGISTER_NAMES
+tm-a29k.h
+@item REG_STACK_SEGMENT
+exec.c
+@item REG_STRUCT_HAS_ADDR
+findvar.c
+@item RE_NREGS
+regex.h
+@item R_FP
+dwarfread.c
+@item R_OK
+xm-altos.h
+@item SEEK_END
+state.c
+@item SEEK_SET
+state.c
+@item SEM
+coffread.c
+@item SET_STACK_LIMIT_HUGE
+When defined, stack limits will be raised to their maximum. Use this
+if your host supports @code{setrlimit} and you have trouble with
+@code{stringtab} in @file{dbxread.c}.
+
+Also used in @file{fork-child.c} to return stack limits before child
+processes are forked.
+@item SHELL_COMMAND_CONCAT
+infrun.c
+@item SHELL_FILE
+infrun.c
+@item SHIFT_INST_REGS
+breakpoint.c
+@item SIGN_EXTEND_CHAR
+regex.c
+@item SIGTRAP_STOP_AFTER_LOAD
+infrun.c
+@item SKIP_PROLOGUE
+tm-m68k.h
+@item SKIP_PROLOGUE_FRAMELESS_P
+blockframe.c
+@item SKIP_TRAMPOLINE_CODE
+infrun.c
+@item SOLIB_ADD
+core.c
+@item SOLIB_CREATE_INFERIOR_HOOK
+infrun.c
+@item STACK_ALIGN
+valops.c
+@item START_INFERIOR_TRAPS_EXPECTED
+infrun.c
+@item STOP_SIGNAL
+main.c
+@item STORE_RETURN_VALUE
+tm-m68k.h
+@item SUN4_COMPILER_FEATURE
+infrun.c
+@item SUN_FIXED_LBRAC_BUG
+dbxread.c
+@item SVR4_SHARED_LIBS
+solib.c
+@item SWITCH_ENUM_BUG
+regex.c
+@item SYM1
+tm-ultra3.h
+@item SYMBOL_RELOADING_DEFAULT
+symfile.c
+@item SYNTAX_TABLE
+regex.c
+@item Sword
+regex.c
+@item TDESC
+infrun.c
+@item TIOCGETC
+inflow.c
+@item TIOCGLTC
+inflow.c
+@item TIOCGPGRP
+inflow.c
+@item TIOCLGET
+inflow.c
+@item TIOCLSET
+inflow.c
+@item TIOCNOTTY
+inflow.c
+@item T_ARG
+coffread.c
+@item T_VOID
+coffread.c
+@item UINT_MAX
+defs.h
+@item UPAGES
+altos-xdep.c
+@item USER
+m88k-tdep.c
+@item USE_GAS
+xm-news.h
+@item USE_O_NOCTTY
+inflow.c
+@item USE_STRUCT_CONVENTION
+values.c
+@item USG
+Means that System V (prior to SVR4) include files are in use.
+(FIXME: This symbol is abused in @file{infrun.c}, @file{regex.c},
+@file{remote-nindy.c}, and @file{utils.c} for other things, at the moment.)
+@item USIZE
+xm-m88k.h
+@item U_FPSTATE
+i386-xdep.c
+@item VARIABLES_INSIDE_BLOCK
+dbxread.c
+@item WRS_ORIG
+remote-vx.c
+@item _LANG_c
+language.c
+@item _LANG_m2
+language.c
+@item __GNUC__
+news-xdep.c
+@item __GO32__
+inflow.c
+@item __HPUX_ASM__
+xm-hp300hpux.h
+@item __INT_VARARGS_H
+printcmd.c
+@item __not_on_pyr_yet
+pyr-xdep.c
+@item alloca
+defs.h
+@item const
+defs.h
+@item GOULD_PN
+gould-pinsn.c
+@item hp800
+xm-hppabsd.h
+@item hpux
+hppabsd-core.c
+@item lint
+valarith.c
+@item longest_to_int
+defs.h
+@item mc68020
+m68k-stub.c
+@item notdef
+gould-pinsn.c
+@item ns32k_opcodeT
+ns32k-opcode.h
+@item sgi
+mips-tdep.c
+@item sparc
+regex.c
+@item sun
+m68k-tdep.c
+@item sun386
+tm-sun386.h
+@item test
+regex.c
+@item ultrix
+xm-mips.h
+@item volatile
+defs.h
+@end table
+
+@node Target Conditionals
+@chapter Target Conditionals
+
+When GDB is configured and compiled, various macros are defined or left
+undefined, to control compilation based on the attributes of the target
+system. These macros and their meanings are:
+
+@emph{NOTE: For now, both host and target conditionals are here.
+Eliminate host conditionals from this list as they are identified.}
+
+@table @code
+@item PUSH_DUMMY_FRAME
+Used in @samp{call_function_by_hand} to create an artificial stack frame.
+@item POP_FRAME
+Used in @samp{call_function_by_hand} to remove an artificial stack frame.
+@item BLOCK_ADDRESS_FUNCTION_RELATIVE
+dbxread.c
+@item KERNELDEBUG
+tm-hppa.h
+@item NO_SYS_FILE
+dbxread.c
+@item PYRAMID_CONTROL_FRAME_DEBUGGING
+pyr-xdep.c
+@item SIGWINCH_HANDLER_BODY
+utils.c
+@item ADDITIONAL_OPTIONS
+main.c
+@item ADDITIONAL_OPTION_CASES
+main.c
+@item ADDITIONAL_OPTION_HANDLER
+main.c
+@item ADDITIONAL_OPTION_HELP
+main.c
+@item ADDR_BITS_REMOVE
+defs.h
+@item ALIGN_STACK_ON_STARTUP
+main.c
+@item ALTOS
+altos-xdep.c
+@item ALTOS_AS
+xm-altos.h
+@item ASCII_COFF
+remote-adapt.c
+@item BADMAG
+coffread.c
+@item BCS
+tm-delta88.h
+@item BEFORE_MAIN_LOOP_HOOK
+main.c
+@item BELIEVE_PCC_PROMOTION
+coffread.c
+@item BELIEVE_PCC_PROMOTION_TYPE
+stabsread.c
+@item BITS_BIG_ENDIAN
+defs.h
+@item BKPT_AT_MAIN
+solib.c
+@item BLOCK_ADDRESS_ABSOLUTE
+dbxread.c
+@item BPT_VECTOR
+tm-m68k.h
+@item BREAKPOINT
+tm-m68k.h
+@item BREAKPOINT_DEBUG
+breakpoint.c
+@item BSTRING
+regex.c
+@item CALL_DUMMY
+valops.c
+@item CALL_DUMMY_LOCATION
+inferior.h
+@item CALL_DUMMY_STACK_ADJUST
+valops.c
+@item CANNOT_FETCH_REGISTER
+hppabsd-xdep.c
+@item CANNOT_STORE_REGISTER
+findvar.c
+@item CFRONT_PRODUCER
+dwarfread.c
+@item CHILD_PREPARE_TO_STORE
+inftarg.c
+@item CLEAR_DEFERRED_STORES
+inflow.c
+@item CLEAR_SOLIB
+objfiles.c
+@item COFF_ENCAPSULATE
+hppabsd-tdep.c
+@item COFF_FORMAT
+symm-tdep.c
+@item CORE_NEEDS_RELOCATION
+stack.c
+@item CPLUS_MARKER
+cplus-dem.c
+@item CREATE_INFERIOR_HOOK
+infrun.c
+@item C_ALLOCA
+regex.c
+@item C_GLBLREG
+coffread.c
+@item DBXREAD_ONLY
+partial-stab.h
+@item DBX_PARM_SYMBOL_CLASS
+stabsread.c
+@item DEBUG
+remote-adapt.c
+@item DEBUG_INFO
+partial-stab.h
+@item DEBUG_PTRACE
+hppabsd-xdep.c
+@item DECR_PC_AFTER_BREAK
+breakpoint.c
+@item DELTA88
+m88k-xdep.c
+@item DEV_TTY
+symmisc.c
+@item DGUX
+m88k-xdep.c
+@item DISABLE_UNSETTABLE_BREAK
+breakpoint.c
+@item DONT_USE_REMOTE
+remote.c
+@item DO_DEFERRED_STORES
+infrun.c
+@item DO_REGISTERS_INFO
+infcmd.c
+@item END_OF_TEXT_DEFAULT
+This is an expression that should designate the end of the text section
+(? FIXME ?)
+@item EXTRACT_RETURN_VALUE
+tm-m68k.h
+@item EXTRACT_STRUCT_VALUE_ADDRESS
+values.c
+@item EXTRA_FRAME_INFO
+frame.h
+@item EXTRA_SYMTAB_INFO
+symtab.h
+@item FILES_INFO_HOOK
+target.c
+@item FLOAT_INFO
+infcmd.c
+@item FOPEN_RB
+defs.h
+@item FP0_REGNUM
+a68v-xdep.c
+@item FPC_REGNUM
+mach386-xdep.c
+@item FP_REGNUM
+parse.c
+@item FPU
+Unused? 6-oct-92 rich@@cygnus.com. FIXME.
+@item FRAMELESS_FUNCTION_INVOCATION
+blockframe.c
+@item FRAME_ARGS_ADDRESS_CORRECT
+stack.c
+@item FRAME_CHAIN
+Given FRAME, return a pointer to the calling frame.
+@item FRAME_CHAIN_COMBINE
+blockframe.c
+@item FRAME_CHAIN_VALID
+frame.h
+@item FRAME_CHAIN_VALID_ALTERNATE
+frame.h
+@item FRAME_FIND_SAVED_REGS
+stack.c
+@item FRAME_GET_BASEREG_VALUE
+frame.h
+@item FRAME_NUM_ARGS
+tm-m68k.h
+@item FRAME_SPECIFICATION_DYADIC
+stack.c
+@item FRAME_SAVED_PC
+Given FRAME, return the pc saved there. That is, the return address.
+@item FUNCTION_EPILOGUE_SIZE
+coffread.c
+@item F_OK
+xm-ultra3.h
+@item GCC2_COMPILED_FLAG_SYMBOL
+dbxread.c
+@item GCC_COMPILED_FLAG_SYMBOL
+dbxread.c
+@item GCC_MANGLE_BUG
+symtab.c
+@item GCC_PRODUCER
+dwarfread.c
+@item GDB_TARGET_IS_HPPA
+This determines whether horrible kludge code in dbxread.c and partial-stab.h
+is used to mangle multiple-symbol-table files from HPPA's. This should all
+be ripped out, and a scheme like elfread.c used.
+@item GDB_TARGET_IS_MACH386
+mach386-xdep.c
+@item GDB_TARGET_IS_SUN3
+a68v-xdep.c
+@item GDB_TARGET_IS_SUN386
+sun386-xdep.c
+@item GET_LONGJMP_TARGET
+For most machines, this is a target-dependent parameter. On the DECstation
+and the Iris, this is a native-dependent parameter, since <setjmp.h> is
+needed to define it.
+
+This macro determines the target PC address that longjmp() will jump
+to, assuming that we have just stopped at a longjmp breakpoint. It
+takes a CORE_ADDR * as argument, and stores the target PC value through
+this pointer. It examines the current state of the machine as needed.
+@item GET_SAVED_REGISTER
+findvar.c
+@item GPLUS_PRODUCER
+dwarfread.c
+@item GR64_REGNUM
+remote-adapt.c
+@item GR64_REGNUM
+remote-mm.c
+@item HANDLE_RBRAC
+partial-stab.h
+@item HAVE_68881
+m68k-tdep.c
+@item HAVE_REGISTER_WINDOWS
+findvar.c
+@item HAVE_SIGSETMASK
+main.c
+@item HAVE_TERMIO
+inflow.c
+@item HEADER_SEEK_FD
+arm-tdep.c
+@item HOSTING_ONLY
+xm-rtbsd.h
+@item HOST_BYTE_ORDER
+ieee-float.c
+@item HPUX_ASM
+xm-hp300hpux.h
+@item HPUX_VERSION_5
+hp300ux-xdep.c
+@item HP_OS_BUG
+infrun.c
+@item I80960
+remote-vx.c
+@item IBM6000_TARGET
+Shows that we are configured for an IBM RS/6000 target. This conditional
+should be eliminated (FIXME) and replaced by feature-specific macros.
+It was introduced in haste and we are repenting at leisure.
+@item IEEE_DEBUG
+ieee-float.c
+@item IEEE_FLOAT
+valprint.c
+@item IGNORE_SYMBOL
+dbxread.c
+@item INIT_EXTRA_FRAME_INFO
+blockframe.c
+@item INIT_EXTRA_SYMTAB_INFO
+symfile.c
+@item INIT_FRAME_PC
+blockframe.c
+@item INNER_THAN
+valops.c
+@item INT_MAX
+defs.h
+@item INT_MIN
+defs.h
+@item IN_GDB
+i960-pinsn.c
+@item IN_SIGTRAMP
+infrun.c
+@item IN_SOLIB_TRAMPOLINE
+infrun.c
+@item ISATTY
+main.c
+@item IS_TRAPPED_INTERNALVAR
+values.c
+@item KERNELDEBUG
+dbxread.c
+@item KERNEL_DEBUGGING
+tm-ultra3.h
+@item LCC_PRODUCER
+dwarfread.c
+@item LOG_FILE
+remote-adapt.c
+@item LONGERNAMES
+cplus-dem.c
+@item LONGEST
+defs.h
+@item CC_HAS_LONG_LONG
+defs.h
+@item PRINTF_HAS_LONG_LONG
+defs.h
+@item LONG_MAX
+defs.h
+@item L_LNNO32
+coffread.c
+@item MACHKERNELDEBUG
+hppabsd-tdep.c
+@item MAINTENANCE
+dwarfread.c
+@item MIPSEL
+mips-tdep.c
+@item MOTOROLA
+xm-altos.h
+@item NBPG
+altos-xdep.c
+@item NEED_POSIX_SETPGID
+infrun.c
+@item NEED_TEXT_START_END
+exec.c
+@item NFAILURES
+regex.c
+@item NNPC_REGNUM
+infrun.c
+@item NOTDEF
+regex.c
+@item NOTDEF
+remote-adapt.c
+@item NOTDEF
+remote-mm.c
+@item NOTICE_SIGNAL_HANDLING_CHANGE
+infrun.c
+@item NO_HIF_SUPPORT
+remote-mm.c
+@item NO_SIGINTERRUPT
+remote-adapt.c
+@item NO_SINGLE_STEP
+infptrace.c
+@item NPC_REGNUM
+infcmd.c
+@item NS32K_SVC_IMMED_OPERANDS
+ns32k-opcode.h
+@item NUMERIC_REG_NAMES
+mips-tdep.c
+@item N_SETV
+dbxread.c
+@item N_SET_MAGIC
+hppabsd-tdep.c
+@item NaN
+tm-umax.h
+@item ONE_PROCESS_WRITETEXT
+breakpoint.c
+@item PC
+convx-opcode.h
+@item PCC_SOL_BROKEN
+dbxread.c
+@item PC_IN_CALL_DUMMY
+inferior.h
+@item PC_LOAD_SEGMENT
+stack.c
+@item PC_REGNUM
+parse.c
+@item PRINT_RANDOM_SIGNAL
+infcmd.c
+@item PRINT_REGISTER_HOOK
+infcmd.c
+@item PRINT_TYPELESS_INTEGER
+valprint.c
+@item PROCESS_LINENUMBER_HOOK
+buildsym.c
+@item PROLOGUE_FIRSTLINE_OVERLAP
+infrun.c
+@item PSIGNAL_IN_SIGNAL_H
+defs.h
+@item PS_REGNUM
+parse.c
+@item PUSH_ARGUMENTS
+valops.c
+@item REGISTER_BYTES
+remote.c
+@item REGISTER_NAMES
+tm-a29k.h
+@item REG_STACK_SEGMENT
+exec.c
+@item REG_STRUCT_HAS_ADDR
+findvar.c
+@item RE_NREGS
+regex.h
+@item R_FP
+dwarfread.c
+@item R_OK
+xm-altos.h
+@item SDB_REG_TO_REGNUM
+Define this to convert sdb register numbers
+into gdb regnums. If not defined, no conversion will be done.
+@item SEEK_END
+state.c
+@item SEEK_SET
+state.c
+@item SEM
+coffread.c
+@item SHELL_COMMAND_CONCAT
+infrun.c
+@item SHELL_FILE
+infrun.c
+@item SHIFT_INST_REGS
+breakpoint.c
+@item SIGN_EXTEND_CHAR
+regex.c
+@item SIGTRAP_STOP_AFTER_LOAD
+infrun.c
+@item SKIP_PROLOGUE
+tm-m68k.h
+@item SKIP_PROLOGUE_FRAMELESS_P
+blockframe.c
+@item SKIP_TRAMPOLINE_CODE
+infrun.c
+@item SOLIB_ADD
+core.c
+@item SOLIB_CREATE_INFERIOR_HOOK
+infrun.c
+@item SP_REGNUM
+parse.c
+@item STAB_REG_TO_REGNUM
+Define this to convert stab register numbers (as gotten from `r' declarations)
+into gdb regnums. If not defined, no conversion will be done.
+@item STACK_ALIGN
+valops.c
+@item START_INFERIOR_TRAPS_EXPECTED
+infrun.c
+@item STOP_SIGNAL
+main.c
+@item STORE_RETURN_VALUE
+tm-m68k.h
+@item SUN4_COMPILER_FEATURE
+infrun.c
+@item SUN_FIXED_LBRAC_BUG
+dbxread.c
+@item SVR4_SHARED_LIBS
+solib.c
+@item SWITCH_ENUM_BUG
+regex.c
+@item SYM1
+tm-ultra3.h
+@item SYMBOL_RELOADING_DEFAULT
+symfile.c
+@item SYNTAX_TABLE
+regex.c
+@item Sword
+regex.c
+@item TARGET_BYTE_ORDER
+defs.h
+@item TARGET_CHAR_BIT
+defs.h
+@item TARGET_COMPLEX_BIT
+defs.h
+@item TARGET_DOUBLE_BIT
+defs.h
+@item TARGET_DOUBLE_COMPLEX_BIT
+defs.h
+@item TARGET_FLOAT_BIT
+defs.h
+@item TARGET_INT_BIT
+defs.h
+@item TARGET_LONG_BIT
+defs.h
+@item TARGET_LONG_DOUBLE_BIT
+defs.h
+@item TARGET_LONG_LONG_BIT
+defs.h
+@item TARGET_PTR_BIT
+defs.h
+@item TARGET_READ_PC
+@item TARGET_WRITE_PC
+@item TARGET_READ_SP
+@item TARGET_WRITE_SP
+@item TARGET_READ_FP
+@item TARGET_WRITE_FP
+These change the behavior of @code{read_pc}, @code{write_pc},
+@code{read_sp}, @code{write_sp}, @code{read_fp} and @code{write_fp}.
+For most targets, these may be left undefined. GDB will call the
+read and write register functions with the relevant @code{_REGNUM} argument.
+
+These macros are useful when a target keeps one of these registers in a
+hard to get at place; for example, part in a segment register and part
+in an ordinary register.
+
+@item TARGET_SHORT_BIT
+defs.h
+@item TDESC
+infrun.c
+@item T_ARG
+coffread.c
+@item T_VOID
+coffread.c
+@item UINT_MAX
+defs.h
+@item USER
+m88k-tdep.c
+@item USE_GAS
+xm-news.h
+@item USE_STRUCT_CONVENTION
+values.c
+@item USIZE
+xm-m88k.h
+@item U_FPSTATE
+i386-xdep.c
+@item VARIABLES_INSIDE_BLOCK
+dbxread.c
+@item WRS_ORIG
+remote-vx.c
+@item _LANG_c
+language.c
+@item _LANG_m2
+language.c
+@item __GO32__
+inflow.c
+@item __HPUX_ASM__
+xm-hp300hpux.h
+@item __INT_VARARGS_H
+printcmd.c
+@item __not_on_pyr_yet
+pyr-xdep.c
+@item GOULD_PN
+gould-pinsn.c
+@item hp800
+xm-hppabsd.h
+@item hpux
+hppabsd-core.c
+@item longest_to_int
+defs.h
+@item mc68020
+m68k-stub.c
+@item ns32k_opcodeT
+ns32k-opcode.h
+@item sgi
+mips-tdep.c
+@item sparc
+regex.c
+@item sun
+m68k-tdep.c
+@item sun386
+tm-sun386.h
+@item test
+(Define this to enable testing code in regex.c.)
+@end table
+
+@node Native Conditionals
+@chapter Native Conditionals
+
+When GDB is configured and compiled, various macros are defined or left
+undefined, to control compilation when the host and target systems
+are the same. These macros should be defined (or left undefined)
+in @file{nm-@var{system}.h}.
+
+@table @code
+@item ATTACH_DETACH
+If defined, then gdb will include support for the @code{attach} and
+@code{detach} commands.
+@item FETCH_INFERIOR_REGISTERS
+Define this if the native-dependent code will provide its
+own routines
+@code{fetch_inferior_registers} and @code{store_inferior_registers} in
+@file{@var{HOST}-nat.c}.
+If this symbol is @emph{not} defined, and @file{infptrace.c}
+is included in this configuration, the default routines in
+@file{infptrace.c} are used for these functions.
+@item GET_LONGJMP_TARGET
+For most machines, this is a target-dependent parameter. On the DECstation
+and the Iris, this is a native-dependent parameter, since <setjmp.h> is
+needed to define it.
+
+This macro determines the target PC address that longjmp() will jump
+to, assuming that we have just stopped at a longjmp breakpoint. It
+takes a CORE_ADDR * as argument, and stores the target PC value through
+this pointer. It examines the current state of the machine as needed.
+@item PROC_NAME_FMT
+Defines the format for the name of a @file{/proc} device. Should be
+defined in @file{nm.h} @emph{only} in order to override the default
+definition in @file{procfs.c}.
+@item PTRACE_FP_BUG
+mach386-xdep.c
+@item PTRACE_ARG3_TYPE
+The type of the third argument to the @code{ptrace} system call, if it exists
+and is different from @code{int}.
+@item REGISTER_U_ADDR
+Defines the offset of the registers in the ``u area''; @pxref{Host}.
+@item USE_PROC_FS
+This determines whether small routines in @file{*-tdep.c}, which
+translate register values
+between GDB's internal representation and the /proc representation,
+are compiled.
+@item U_REGS_OFFSET
+This is the offset of the registers in the upage. It need only be
+defined if the generic ptrace register access routines in
+@file{infptrace.c} are being used (that is,
+@file{infptrace.c} is configured in, and
+@code{FETCH_INFERIOR_REGISTERS} is not defined). If the default value
+from @file{infptrace.c} is good enough, leave it undefined.
+
+The default value means that u.u_ar0 @emph{points to} the location of the
+registers. I'm guessing that @code{#define U_REGS_OFFSET 0} means that
+u.u_ar0 @emph{is} the location of the registers.
+@end table
+
+@node Obsolete Conditionals
+@chapter Obsolete Conditionals
+
+Fragments of old code in GDB sometimes reference or set the following
+configuration macros. They should not be used by new code, and
+old uses should be removed as those parts of the debugger are
+otherwise touched.
+
+@table @code
+@item STACK_END_ADDR
+This macro used to define where the end of the stack appeared, for use
+in interpreting core file formats that don't record this address in the
+core file itself. This information is now configured in BFD, and GDB
+gets the info portably from there. The values in GDB's configuration
+files should be moved into BFD configuration files (if needed there),
+and deleted from all of GDB's config files.
+
+Any @file{@var{foo}-xdep.c} file that references STACK_END_ADDR
+is so old that it has never been converted to use BFD. Now that's old!
+@end table
+
+@node XCOFF
+@chapter The XCOFF Object File Format
+
+The IBM RS/6000 running AIX uses an object file format called xcoff.
+The COFF sections, symbols, and line numbers are used, but debugging
+symbols are dbx-style stabs whose strings are located in the
+@samp{.debug} section (rather than the string table). For more
+information, @xref{Top,,,stabs,The Stabs Debugging Format}, and search
+for XCOFF.
+
+The shared library scheme has a nice clean interface for figuring out
+what shared libraries are in use, but the catch is that everything which
+refers to addresses (symbol tables and breakpoints at least) needs to be
+relocated for both shared libraries and the main executable. At least
+using the standard mechanism this can only be done once the program has
+been run (or the core file has been read).
+
+@contents
+@bye
diff --git a/gnu/usr.bin/gdb/doc/h8-cfg.texi b/gnu/usr.bin/gdb/doc/h8-cfg.texi
new file mode 100644
index 000000000000..823c7c244b5a
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/h8-cfg.texi
@@ -0,0 +1,47 @@
+@c GDB version number is recorded in the variable GDBVN
+@include GDBvn.texi
+@c
+@set AGGLOMERATION
+@clear AMD29K
+@set BARETARGET
+@clear CONLY
+@set DOSHOST
+@clear FORTRAN
+@clear FSFDOC
+@clear GDBSERVER
+@clear GENERIC
+@set H8
+@set H8EXCLUSIVE
+@clear HAVE-FLOAT
+@clear I960
+@clear MOD2
+@clear NOVEL
+@clear POSIX
+@set PRECONFIGURED
+@clear REMOTESTUB
+@set SIMS
+@clear SERIAL
+@clear SPARC
+@clear ST2000
+@clear VXWORKS
+@clear Z8K
+@c ----------------------------------------------------------------------
+@c STRINGS:
+@c
+@c Name of GDB program. Used also for (gdb) prompt string.
+@set GDBP gdb
+@c
+@c Name of GDB product. Used in running text.
+@set GDBN GDB
+@c
+@c Name of GDB initialization file.
+@set GDBINIT .gdbinit
+@c
+@c Name of target.
+@set TARGET Hitachi Microprocessors
+@c
+@c Name of GCC product
+@set NGCC GCC
+@c
+@c Name of GCC program
+@set GCC gcc
diff --git a/gnu/usr.bin/gdb/doc/libgdb.texinfo b/gnu/usr.bin/gdb/doc/libgdb.texinfo
new file mode 100644
index 000000000000..c67c3a88359d
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/libgdb.texinfo
@@ -0,0 +1,1471 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename libgdb.info
+@settitle Libgdb
+@setchapternewpage odd
+@c %**end of header
+
+@ifinfo
+This file documents libgdb, the GNU library for symbolic debuggers.
+
+Copyright 1993 Cygnus Support
+
+Permission is granted to ...
+@end ifinfo
+
+@c This title page illustrates only one of the
+@c two methods of forming a title page.
+
+@titlepage
+@title Libgdb
+@subtitle Version 0.1
+@subtitle 27 Sep 1993
+@author Thomas Lord
+
+@c The following two commands
+@c start the copyright page.
+@page
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1993 COPYRIGHT-OWNER
+
+Published by ...
+
+Permission is granted to ...
+@end titlepage
+
+@node Top, Overview, (dir), (dir)
+
+@ifinfo
+
+Libgdb is a library which provides the core functionality of a symbolic
+debugger. It is derived from GNU GDB and depends on the BFD library.
+
+This is an early draft of this document. Subsequent versions will likely
+contain revisions, deletions and additions.
+
+This document applies to version 0.0.
+
+Text marked `[[[' indicates areas which require expansion.
+
+Many nodes describe library entry points by giving a prototype and brief
+description:
+
+@deftypefun {const char **} gdb_warranty ()
+(warranty_info)
+Return a pointer to the text of the GDB disclaimer.
+@end deftypefun
+
+The parenthesized symbols (e.g. `(warranty_info)') refer to the
+existing GDB source and generally indicate where to find code with
+which to implement the library function.
+@end ifinfo
+
+@menu
+* Copying:: Your rights and freedoms.
+* Overview:: The basics of libgdb and this document.
+* Conventions:: Programming conventions for users of libgdb.
+* Targets:: Selecting debugging targets and symbol tables.
+* Symtabs:: Accessing symbol tables and debugging information.
+* Source:: Relating inferiors to source files.
+* Running:: Creating, continuing, and stepping through an
+ inferior process.
+* Stopping:: Using breakpoints, signaling an inferior.
+* Stack:: Accessing an inferior's execution stack.
+* Expressions:: How to parse and evaluate expressions in the
+ context of an inferior.
+* Values:: Data from the inferior, the values of expressions.
+* Examining:: Formatting values as strings.
+* Types:: Examining the types of an inferiors data.
+@end menu
+
+
+@node Copying, Overview, top, top
+@comment node-name, next, previous, up
+@chapter Copying
+@cindex copying
+
+blah blah
+
+@node Overview, Conventions, Copying, top
+@comment node-name, next, previous, up
+@chapter Overview
+@cindex overview
+@cindex definitions
+
+
+Libgdb is a library which provides the core functionality of a symbolic
+debugger. It is derived from GNU GDB and depends on the BFD library.
+
+target
+inferior
+
+
+
+@node Conventions, Targets, Overview, top
+@comment node-name, next, previous, up
+@chapter Programming Conventions for Libgdb Clients
+@cindex Conventions
+
+@heading Naming Conventions
+
+Names intentionally exported from libgdb all begin @code{gdb_}
+as in @code{gdb_use_file}.
+
+
+@heading Error Returns
+
+Libgdb functions that might not succeed generally have a return
+type of @code{gdb_error_t}.
+
+@deftypefun {const char *} gdb_error_msg (gdb_error_t @var{error})
+returns a reasonable error message for @var{error}.
+@end deftypefun
+
+
+@heading Blocking I/O
+
+[[[....]]]
+
+
+@heading Global Parameters
+@subheading the current directory
+@deftypefun gdb_error_t gdb_cd (char * @var{dir})
+Specify gdb's default directory as well as the working
+directory for the inferior (when first started).@*
+(cd_command)
+@end deftypefun
+
+@deftypefun {char *} gdb_copy_pwd ()
+Make a copy of the name of gdb's default directory.@*
+(pwd_command)
+@end deftypefun
+
+
+@subheading controlling the input/output radix
+@deftypefun gdb_error_t gdb_set_base (int)
+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.@*
+(set_base_command)
+@end deftypefun
+
+@deftypefun gdb_error_t gdb_set_input_radix (int)
+@deftypefunx gdb_error_t gdb_set_output_radix (int)
+@deftypefunx gdb_error_t gdb_set_radix (int)
+Valid output radixes are only 0 (heuristic), 10, and 16.@*
+(set_radix)
+@end deftypefun
+
+
+@subheading manipulating environments
+@deftp Type {struct environ}
+@example
+struct environ
+@{
+ int allocated;
+ char ** vector;
+@}
+@end example
+A `struct environ' holds a description of environment
+variable bindings.
+@end deftp
+
+@deftypefun {struct environ *} gdb_make_environ ()
+Create a new (empty) environment.@*
+(make_environ)
+@end deftypefun
+
+@deftypefun {void} gdb_free_environ (struct environ *)
+Free an environment allocated by `gdb_make_environ'.@*
+(free_environ)
+@end deftypefun
+
+@deftypefun {void} gdb_init_environ (struct environ * env)
+Copy the processes environment into ENV.@*
+(init_environ)
+@end deftypefun
+
+@deftypefun {char **} gdb_get_in_environ (const struct environ * @var{env}, const char * @var{var})
+Look up the binding of @var{var} in @var{env}.@*
+(get_in_environ)
+@end deftypefun
+
+
+@deftypefun {void} gdb_set_in_environ (struct environ * @var{env}, const char * @var{var}, const char * @var{value})
+Lookup/bind variables within an environment.
+(set_in_environ)
+@end deftypefun
+
+
+@subheading legal notices
+@deftypefun {char **} gdb_copying ()
+@deftypefunx {char **} gdb_warranty ()
+These return pointers to NULL terminated arrays of strings.
+They contain text which describes the conditions under which
+libgdb is distributed (`gdb_copying') and which explains to
+users that there is no warranty for libgdb (`gdb_warranty').@*
+(show_warranty_command, show_copying_command)
+@end deftypefun
+
+
+@subheading the inferior's terminal
+@deftypefun void gdb_inferiors_io (int @var{std_in}, int @var{std_out}, int @var{std_err})
+Assert that the given descriptors should be copied into
+descriptors 0, 1, and 2 of the inferior when it
+is next run.
+@end deftypefun
+
+
+@heading callbacks
+
+One idiom used in several places deserves mention.
+At times, it makes sense for libgdb functions to
+invoke functions provided by the libgdb client.
+Where this is the case, callback structures are used
+to refer to client functions. For example, here
+are the declarations for a callback to which libgdb
+will pass an integer and a character pointer.
+
+@example
+struct a_gdb_cback;
+typedef void (*a_gdb_cback_fn) (struct a_gdb_cback *,
+ int, char *);
+@end example
+
+Suppose the client wants the callback to be implemented
+by @code{foo} which we will assume takes not only the integer
+and character pointer, but also a floating point number.
+The client could use these declarations:
+
+@example
+struct my_cback
+@{
+ struct a_gdb_cback gdb_cback; /* must be first */
+ float magic_number;
+@};
+
+void
+foo_helper (struct a_gdb_cback * callback, int i, char * cp)
+@{
+ foo ( ((struct my_cback *)callback)->magic_number, i, c);
+@}
+
+struct my_cback
+@{
+ foo_helper,
+ 1079252848.8
+@} the_cback;
+@end example
+
+
+@subheading stream callbacks
+
+A common kind of callback takes just a character pointer,
+presumed to point to part or all of an informational
+message.
+
+@example
+struct gdb_stream_cback;
+typedef void (*gdb_stream_cback_fn) (struct gdb_stream_cback *,
+ char *);
+@end example
+
+
+@subheading integer callbacks
+
+Another common kind of callback takes just an integer.
+
+@example
+struct gdb_int_cback;
+typedef void (*gdb_int_cback_fn) (struct gdb_int_cback *, int);
+@end example
+
+@node Targets, Symtabs, Conventions, top
+@comment node-name, next, previous, up
+@chapter Selecting Targets and Symbol Tables for Debugging
+@cindex targets
+
+@deftypefun gdb_error_t gdb_use_file (char * @var{filename})
+Arrange to read both executable code and symbol table information
+from FILENAME.
+
+This is exactly equivalent to a sequence of two calls:
+@example
+ gdb_use_exec_file (filename);
+ gdb_use_symbol_file (filename);
+@end example
+(file_command)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_use_exec_file (char * @var{filename})
+Read the code to debug from `filename'.@*
+(exec_file_command)
+@end deftypefun
+
+
+@deftypefun {char *} gdb_get_exec_file ()
+Return the name of the executable file as a string or 0
+if there is none.
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_use_core (char * @var{filename})
+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; GDB
+can access the executable file itself for other parts.
+
+If @var{filename} is @code{NULL}, no core file is used.@*
+(core_file_command)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_use_symbol_file (char * @var{filename})
+Arrange to read symbol table information from `filename'.
+
+This is the same as:
+
+ gdb_symbol_file_add (filename, 1, (CORE_ADDR)0, 1, 0, 0);
+
+See @code{gdb_symbol_file_add} for finer control over the symbol
+table.@*
+(symbol_file_command)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_symbol_file_add (@var{name}, @var{verbose}, @var{text_addr}, @var{replace}, @var{eager})
+Arrange to read additional symbol table information from
+the file `name'.
+
+The arguments are:
+@itemize @minus
+@item struct gdb_stream_cback * @var{info_out}
+
+Callback to handle informational output.
+
+@item char * @var{name}
+
+If not 0, verbose output will occur.
+
+@item int @var{be_verbose}
+
+Regulates the amount of informational output produced.
+
+@item CORE_ADDR @var{text_addr}
+
+is the address at which the named file is presumed to have
+been loaded.
+
+@item int @var{replace}@*
+
+If not 0, this will become the only file
+in the symbol table -- all previously loaded
+symbol table information will be discarded.
+
+@item int @var{readnow}
+
+If not 0, eagerly read symbols from this file,otherwise
+symbols will only be read lazily (as needed).
+@end itemize
+@end deftypefun
+
+
+@deftypefun {char *} gdb_copy_exec_path ()
+Make a copy of the execution path.@*
+[[[implement: strsave(get_in_environ (inferior_environ, "PATH"));]]]@*
+(path_info)
+@end deftypefun
+
+
+@deftypefun void gdb_mod_exec_path (char * @var{dirnames})
+Add zero or more directories to the front of the execution path.
+@var{dirnames} should be a colon separated list of directory names.@*
+(path_command)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_target_device (char * @var{name})
+Connects the libgdb host environment to a target machine
+or process.@*
+(target foo)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_set_baud (int @var{rate})
+If using a remote target connected by a serial port,
+use RATE as the communication speed.
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_set_target_debugging (int @var{level})
+Choose the level of verboseness of with which a remote
+target produces debugging output.
+@end deftypefun
+
+@node Symtabs, Source, Targets, top
+@comment node-name, next, previous, up
+@chapter Accessing symbol tables and debugging information.
+@cindex Symtabs
+@cindex {Symbol Tables}
+
+@deftp Type {struct symtab}
+Each source file is represented by a struct symtab.
+In many contexts, @code{struct symtab *} is used in preference
+to a {char *} filename to refer to the source.
+@end deftp
+
+
+@deftypefun {char *} gdb_symtab_to_filename (struct symtab *)
+@deftypefunx {char *} gdb_symtab_to_dirname (struct symtab *)
+Return the location of the file corresponding to this symtab.
+@code{gdb_symtab_to_dirname} might return @code{NULL} if no directory
+is known. @code{gdb_symtab_to_line_count} might return -1 if line
+number information is unavailable.
+@end deftypefun
+
+@deftypefun int gdb_symtab_to_line_count (struct symtab *)
+(See also `Source')
+@end deftypefun
+
+
+@deftypefun {struct symtab *} gdb_filename_to_symtab (char * @var{filename})
+Lookup the symbol table of a source file named NAME.@*
+(lookup_symtab)
+@end deftypefun
+
+
+@deftp Type {struct symtab_and_line}
+@example
+struct symtab_and_line
+@{
+ struct symtab *symtab;
+ int line;
+ CORE_ADDR pc;
+ CORE_ADDR end;
+@}
+@end example
+
+@code{struct symtab_and_line} is used to refer to a particular line
+of source code. It is used to locate breakpoints in the source
+code and the executable.
+
+@code{line} starts at 1 and proceeds through symtab->nlines.
+0 is never a valid line number; it is used to indicate
+that line number information is not available.
+@end deftp
+
+
+@deftypefun {struct symtab_and_line} gdb_find_pc_line (CORE_ADDR @var{pc}, int @var{notcurrent})
+Find the source file and line number for a given @var{pc} value.
+Return a structure containing a symtab pointer, a line number,
+and a pc range for the entire source line.
+The value's @code{.pc} field is NOT the specified @var{pc}.
+@var{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.@*
+(find_pc_line)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_find_line (struct symtab_and_line * @var{out}, struct symtab *, int)
+Create a symtab_and_line for a given symtab and line number.
+In other words, if you know the source file and line,
+this returns a location for the breakpoint.@*
+(resolve_sal_pc)
+@end deftypefun
+
+
+@deftypefun {struct symtabs_and_lines} gdb_decode_line (@var{argptr}, @var{firstln}, @var{default_symtab}, @var{default_line}, @var{canonical})
+@example
+ char ** argptr;
+ int funfirstline;
+ struct symtab * default_symtab;
+ int default_line;
+ char *** canonical;
+@end example
+ Parse a string that specifies a line number in GDB syntax.
+ @var{argptr} 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 minimal symbol
+ table.
+
+ 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.
+ If CANONICAL is non-NULL, store an array of strings containing the
+ canonical line specs there if necessary. Currently overloaded
+ member functions and line numbers or static functions without a
+ filename yield a canonical line spec. The array and the line spec
+ strings are allocated on the heap, it is the callers responsibility
+ to free them.
+
+ 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.
+
+ The return value of this function includes allocated memory
+ which the caller is responsible for freeing:
+
+ struct symtabs_and_lines sals;
+ sals = decode_line_spec (arg, 1);
+ ....
+ free (sals.sals);@*
+(decode_line_1)
+@end deftypefun
+
+
+@deftp Type {struct block *}
+Lexical environments in the program are represented by struct block.
+These are useful as arguements to expression parsing functions (see
+`Expressions').
+@end deftp
+
+
+@deftypefun {struct block *} gdb_block_for_pc (CORE_ADDR)
+Return the innermost lexical block containing the
+specified pc value, or 0 if there is none.@*
+(block_for_pc)
+@end deftypefun
+
+
+@deftypefun {struct block *} gdb_get_frame_block (FRAME @var{frame})
+This returns the block being executed by a given
+stack frame (see `Stack')@*
+(get_frame_block)
+@end deftypefun
+
+
+@deftypefun int gdb_find_line_pc_range (@var{syms}, @var{line}, @var{start_out}, @var{end_out})
+@example
+struct symtab * @var{start_out};
+int @var{line};
+CORE_ADDR * @var{start_out};
+CORE_ADDR * @var{end_out};
+@end example
+Find the range of pc values in a line.@*
+Store the starting pc of the line into @code{*@var{startptr}}.
+and the ending pc (start of next line) into @code{*@var{endptr}}.
+
+Returns 1 to indicate success.@*
+Returns 0 if could not find the specified line.@*
+(find_line_pc_range)
+@end deftypefun
+
+
+@deftypefun int gdb_find_pc_partial_function (@var{pc}, @var{name}, @var{address}, @var{endaddr})
+@example
+CORE_ADDR @var{pc};
+char **@var{name};
+CORE_ADDR *@var{address};
+CORE_ADDR *@var{endaddr};
+@end example
+Finds the "function" (text symbol) that is smaller than @var{pc} but
+greatest of all of the potential text symbols. Sets @code{*@var{name}}
+and/or @code{*@var{address}} conditionally if that pointer is non-null. If
+@var{endaddr} is non-null, then set @code{*@var{endaddr}} to be the end of
+the function (exclusive), but passing @var{endaddr} as non-null means that
+the function might cause symbols to be read. This function either succeeds
+or fails (not halfway succeeds). If it succeeds, it sets
+@code{*@var{name}}, @code{*@var{address}}, and @code{*@var{endaddr}} to
+real information and returns 1. If it fails, it sets @code{*@var{name}},
+@code{*@var{address}}, and @code{*@var{endaddr}} to zero and returns 0.
+
+@example
+ pc = get_frame_pc (selected_frame);
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error ("No function contains program counter for selected frame.\n");
+@end example
+(find_pc_partial_function)
+@end deftypefun
+
+
+@deftypefun void gdb_list_symbols (@var{info_out}, @var{regexp}, @var{class}, @var{bpt})
+@example
+struct gdb_stream_cback * @var{info_out};
+char * @var{regexp};
+int @var{class};
+int @var{bpt};
+@end example
+List all symbols (if @var{regexp} is NULL) or all symbols matching @var{regexp}.
+
+
+If @var{class} is ...
+@itemize @bullet
+@item
+0, list all symbols except functions, type names, and
+constants (enums).
+@item
+1, list only functions.
+@item
+2, list only type names.
+@item
+3, list only method names.
+@end itemize
+BPT is non-zero if set a breakpoint at the functions we find.@*
+(variables_info, functions_info, types_info, list_symbols)
+@end deftypefun
+
+
+@deftypefun int gdb_locals_info (struct gdb_stream_cback * @var{info_out}, FRAME @var{frame})
+Print all the local variables in the given 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 @var{frame}.@*
+(locals_info)
+@end deftypefun
+
+
+@deftypefun int print_frame_arg_vars (struct gdb_stream_cback *, FRAME)
+Similar to `gdb_locals_info'.@*
+(args_info)
+@end deftypefun
+
+@node Source, Running, Symtabs, top
+@comment node-name, next, previous, up
+@chapter Relating Inferiors to Source Files
+@cindex source
+@cindex {source files}
+
+How to find the source that corresponds to executable code and the
+executable code that corresponds to a line of source.
+
+@deftypefun {char *} gdb_copy_source_fullname (struct symtab *@var{s})
+Return a copy of the full path name to a source file.
+(See `Symtabs' for more information about filenames
+and symbol tables.).
+@end deftypefun
+
+
+@deftypefun int gdb_open_source_file (struct symtab *@var{s})
+Open a source file corresponding to @var{s}. Returns a file descriptor
+or negative number for error.
+[[[We may decide not to provide this function.]]]@*
+(open_source_file)
+@end deftypefun
+
+
+@deftypefun int gdb_source_line_pos (struct symtab * @var{s}, int @var{lineno})
+Return the byte offset of a given line of source
+or a negative number if @var{lineno} is out of range.@*
+(find_source_lines)
+@end deftypefun
+
+
+ -- IDIOM: The gdb command `show directories'.
+@example
+ puts_filtered ("Source directories searched: ");
+ puts_filtered (source_path);
+ puts_filtered ("\n");
+@end example
+(show_directories)
+
+
+@deftypefun {char *} gdb_source_path ()
+Return the path in which source files are sought.@*
+(source_path)
+@end deftypefun
+
+
+@deftypefun void gdb_modify_source_path (char * @var{dirnames})
+Change the source path according to dirnames.@*
+(directory_command)
+@end deftypefun
+
+
+See `Symtabs' for functions relating symbol tables to files.
+(source_info)
+
+
+See `Symtabs' for functions relating source lines to PC values.
+(line_info)
+
+
+[[[Try to expose sources_info without having to introduce struct object *?]]]
+(sources_info)
+
+
+@node Running, Stopping, Source, top
+@comment node-name, next, previous, up
+@chapter Creating, Continuing, and Stepping Through an Inferior Process
+@cindex running
+
+
+@deftypefun gdb_error_t gdb_target_create_inferior (@var{exec}, @var{args}, @var{environ})
+@example
+char * @var{exec_file};
+char * @var{inferior_args};
+char ** @var{inferior_environment_vector};
+@end example
+Create a running inferior.
+[[[I think the exec_file parameter is redundant. Perhaps this will take
+only two arguments.]]]@*
+(run_command, target_create_inferior)
+@end deftypefun
+
+
+@deftypefun int gdb_target_has_execution ()
+Return non-0 if an inferior is running.@*
+(target_has_execution)
+@end deftypefun
+
+
+@deftypefun void gdb_target_kill ()
+Kill the inferior process. Make it go away.
+The inferior may become a core file.
+If so, gdb_target_has_stack() will return non-0.@*
+(target_kill)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_step_1 (@var{skip_subs}, @var{single_inst}, @var{repeat_count})
+@example
+int skip_subs;
+int single_inst;
+int repeat_count;
+@end example
+Continue a program a little bit. Roughly:
+@example
+ for (; count > 0; --count)
+ gdb_clear_proceed_status ();
+ gdb_proceed (...);
+@end example
+(next_command, nexti_command, step_command, stepi_command)
+@end deftypefun
+
+
+ -- IDIOM: Continuing a program where it stopped.
+@example
+ gdb_clear_proceed_status ();
+ gdb_proceed ((CORE_ADDR) -1, -1, 0);
+@end example
+(continue_command)
+
+
+ -- IDIOM: Continuing a program giving it a specified signal.
+@example
+ gdb_clear_proceed_status ();
+ gdb_proceed ((CORE_ADDR) -1, signum, 0);
+@end example
+(signal_command)
+
+
+@deftypefun {char *} strtosigno (char * @var{str})
+(Typical use:)
+@example
+ signum = strtosigno (signum_exp);
+
+ if (signum == 0)
+ /* Not found as a name, try it as an expression. */
+ signum = parse_and_eval_address (signum_exp);
+
+ gdb_clear_proceed_status ();
+ gdb_proceed ();
+@end example
+@end deftypefun
+
+
+ -- IDIOM: Continuing a program at a specified address.
+@example
+ gdb_clear_proceed_status ();
+ gdb_proceed (addr, 0, 0);
+@end example
+(jump_command)
+
+
+@deftypefun gdb_error_t gdb_finish ()
+"finish": Set a temporary breakpoint at the place
+the selected frame will return to, then continue.
+This is a convenience function but it summarizes a lot
+of other stuff.@*
+(finish_command)
+@end deftypefun
+
+
+@deftypefun void gdb_clear_proceed_status ()
+Clear out all variables saying what to do when inferior is continued.
+First do this, then set the ones you want, then call @code{gdb_proceed}.
+
+ [[[Some of these should be documented, others hidden.]]]
+@example
+ The variables are:
+ trap_expected = 0;
+ step_range_start = 0;
+ step_range_end = 0;
+ step_frame_address = 0;
+ step_over_calls = -1;
+ 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);
+@end example
+(clear_proceed_status)
+@end deftypefun
+
+
+@deftypefun void gdb_proceed (CORE_ADDR @var{addr}, int @var{signal}, int @var{step})
+Basic routine for continuing the program in various fashions.
+
+@var{addr} is the address to resume at, or -1 for resume where stopped.@*
+@var{signal} is the signal to give it, or 0 for none,
+or -1 for act according to how it stopped.@*
+@var{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 @code{gdb_clear_proceed_status} before calling proceed.
+(See the documentation for @code{gdb_clear_proceed_status} for more
+parameters to @code{gdb_proceed}).@*
+(proceed)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_return (value @var{return_value}, FRAME @var{frame})
+Make @var{frame} return to @var{value} to it's caller.
+Unlike the other functions in this section, this doesn't
+call proceed.
+(return_command)
+@end deftypefun
+
+
+@deftypefun int gdb_inferior_pid ()
+0 or the valid pid of an inferior.
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_attach (int @var{pid})
+takes a program started up outside of gdb and
+`attaches'' to it. This stops it cold in its tracks and allows us
+to start debugging it. and wait for the trace-trap that results
+from attaching.@*
+(attach_command)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_detach (int @var{signal_num})
+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).@*
+(detach_command)
+@end deftypefun
+
+@node Stopping, Stack, Running, top
+@comment node-name, next, previous, up
+@chapter Using Breakpoints, Signaling an Inferior
+@cindex stopping
+@cindex breakpoints
+
+
+@deftp Type {struct breakpoint}
+Breakpoints are typically represented @code{struct breakpoint *}.
+@end deftp
+
+
+@deftypefun {struct breakpoint *} gdb_find_breakpoint (int)
+Find a breakpoint given it's number (return 0 if it doesn't exist).
+@end deftypefun
+
+@deftypefun gdb_error_t gdb_set_break (struct breakpoint * @var{brk_out}, struct symtab_and_line)
+@deftypefunx gdb_error_t gdb_set_tbreak (struct breakpoint *, struct symtab_and_line)
+@deftypefunx gdb_error_t gdb_set_until (struct breakpoint *, struct symtab_and_line)
+These three are like their command language counterparts.
+They are front ends to `gdb_set_raw_breakpoint'.
+See `Symtabs' for sources of `struct symtab_and_line'.@*
+(break_command, break_command_1, until_command, tbreak_command)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_set_watchpt (@var{brk_out}, @var{exp_string}, @var{exp}, @var{exp_valid_block})
+@example
+struct breakpoint * @var{brk_out};
+char * @var{exp_string};
+struct expression * @var{exp};
+struct block * @var{expression_valid_block};
+@end example
+Set a watchpoint for the given expression.@*
+(watch_command)
+@end deftypefun
+
+
+@deftypefun void gdb_set_ignore_count (int @var{bptnum}, int @var{count})
+Set ignore-count of breakpoint number BPTNUM to COUNT.@*
+(set_ignore_count)
+@end deftypefun
+
+
+@deftypefun {struct gdb_bp_condition *} gdb_set_condition (@var{bp}, @var{exp_str}, @var{cond})
+@example
+int @var{pbtnum};
+char * @var{exp_str};
+struct gdb_bp_condition * @var{cond};
+
+typedef int (*gdb_bp_fn) (struct gdb_bp_condition *, int bp_num);
+struct gdb_bp_condition
+@{
+ gdb_bp_fn fn;
+@};
+@end example
+Add a condition to a breakpoint.
+The condition is a callback which should return
+0 to skip the breakpoint, and 1 to break at it.
+It is called at times when the break might occur.
+
+A useful application of these callbacks to attach
+an expression to breakpoints like the gdb `condition'
+command. See `Expressions' for the parsing and
+evaluation of expressions.@*
+(condition_command)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_enable_breakpoint (struct breakpoint * @var{bpt}, int @var{once})
+@deftypefunx gdb_error_t gdb_disable_breakpoint (struct breakpoint * @var{bpt})
+Enable/disable a breakpoint. If `once' is not 0, the
+breakpoint is only temporarily enabled.@*
+(enable_breakpoint, disable_breakpoint, enable_command)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_delete_breakpoint (struct breakpoint * @var{bpt})
+Delete a breakpoint and clean up all traces of it in the
+data structures.@*
+(delete_breakpoint)
+@end deftypefun
+
+
+@deftypefun void gdb_clear_breakpoints (struct symtabs_and_lines * @var{sals})
+Clear breakpoints from a list of program locations as
+might be returned by `gdb_decode_line' (see `Symtabs').@*
+(clear_command)
+@end deftypefun
+
+
+@deftypefun {static struct symtabs_and_lines} get_catch_sals (int @var{this_level_only})
+Return the line numbers of all exception handlers currently
+active (or `this_level_only'?? [[[?]]]).
+[[[The implementation should remember to resolve_sal_pc]]]
+@end deftypefun
+
+
+@deftp Type {struct breakpoint_cback}
+@example
+typedef void (*breakpoint_cback_fn) (struct breakpoint_cback *, int bp_num);
+struct breakpoint_cback
+@{
+ breakpoint_cback_fn fn;
+@};
+@end example
+
+Breakpoints can have an associated function which is called
+when the program is stopped by that breakpoint.@*
+(commands_command)
+@end deftp
+
+
+@deftypefun {struct breakpoint_cback *} gdb_set_breakpoint_cback (int @var{bp_num}, struct breakpoint_cback *)
+This sets a breakpoint callback and returns the previous callback value
+for that breakpoint.
+[[[In the long run, the command interpreter should be available
+ for the use of hooks like this one.]]]
+@end deftypefun
+
+
+@deftypefun {struct breakpoint_cback *} gdb_get_breakpoint_cback (int @var{bp_num})
+@end deftypefun
+
+
+@deftypefun void gdb_breakpoints_info (struct gdb_stream_cback, int @var{bp_num}, int @var{watches})
+Print information on breakpoint number @var{bnum}, or -1 if all.
+If @var{watches} is zero, process only breakpoints; if @var{watches}
+is nonzero, process only watchpoints.
+[[[In the long run, expose the information read off by this function.]]]@*
+(info breakpoints, info watchpoints, breakpoints_info, breakpoint_1)
+@end deftypefun
+
+
+@deftypefun void gdb_catch_info (struct gdb_stream_cback *)
+Print a list of all the exception handlers that are active in the
+current stack frame at the current point of execution.@*
+(catch_info)
+@end deftypefun
+
+
+@deftypefun void gdb_handle_command (char * @var{args})
+Takes arguments like the gdb command `handle' and has
+the same effect.@*
+(handle_command)
+@end deftypefun
+
+
+@deftypefun void gdb_signals_info (struct gdb_stream_cback *)
+Show how signals are handled.@*
+(signals_info)
+@end deftypefun
+
+
+@node Stack, Expressions, Stopping, top
+@comment node-name, next, previous, up
+@chapter Accessing An Inferior's Execution Stack
+@cindex stack
+@cindex FRAME
+@cindex {stack frames}
+
+
+
+@deftp Type FRAME
+This type representing active stack frames in the inferior.
+Consider this type opaque.
+@end deftp
+
+
+@deftypefun FRAME gdb_get_innermost_frame ()
+Returns the innermost frame or the frame most recently designated
+as current by a call to gdb_set_current_frame.@*
+(get_current_frame)
+@end deftypefun
+
+
+@deftypefun FRAME gdb_get_caller_frame (FRAME @var{frame})
+Return the frame that called @var{frame}.@*
+If @var{frame} is the original frame (it has no caller), return 0.@*
+(get_prev_frame)
+@end deftypefun
+
+
+@deftypefun FRAME gdb_get_called_frame (FRAME @var{frame})
+Return the frame that @var{frame} calls (0 if @var{frame} is the innermost
+frame).@*
+(get_next_frame)
+@end deftypefun
+
+
+@deftypefun FRAME gdb_parse_frame_specification (char * @var{frame_exp})
+Read a frame specification in whatever the appropriate format is.
+Call @code{error}() If the specification is in any way invalid (i.e.
+this function never returns NULL).@*
+(parse_frame_specification)
+@end deftypefun
+
+
+@deftypefun CORE_ADDR get_frame_pc (FRAME @var{frame})@*
+(Example use: Implementing @code{disassemble_command})@*
+(get_frame_pc)
+@end deftypefun
+
+
+@deftypefun FRAME gdb_selected_frame ()
+The "selected" stack frame is used by default for local and
+arg access. May be @code{NULL}, for no selected frame.@*
+(variable selected_frame)
+@end deftypefun
+
+
+@deftypefun int gdb_selected_frame_level ()
+Level of the selected frame:@*
+0 for innermost,@*
+1 for its caller,@*
+or -1 for frame specified by address with no defined level.@*
+(variable selected_frame_level)
+@end deftypefun
+
+
+@deftypefun void gdb_select_frame (FRAME @var{frame}, int @var{level})
+Select frame @var{frame}, and note that its stack level is @var{level}.
+@var{level} may be -1 if an actual level number is not known.
+Calls @code{set_language} to establish the correct language for the
+selected frame.
+@end deftypefun
+
+
+ -- IDIOM: Computing Frame Levels@*
+@example
+/* Try to figure out what level this frame is as before a
+ call to gdb_select_frame. But if there is
+ no current stack, don't error out, just pass -1
+ instead. */
+frame1 = 0;
+level = -1;
+if (get_current_frame()) @{
+ for (frame1 = get_prev_frame (0);
+ frame1 && frame1 != frame;
+ frame1 = get_prev_frame (frame1))
+ level++;
+@}
+@end example
+
+
+@deftypefun void gdb_print_stack_frame (@var{cback}, @var{frame}, @var{level}, @var{source})
+@example
+struct gdb_stream_cback * @var{cback};
+FRAME @var{frame};
+int @var{level};
+int @var{source};
+@end example
+Print a stack frame briefly. @var{frame} should be the frame id
+and @var{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 @var{source} is 1, print the source line as well.@*
+If @var{source} is -1, print ONLY the source line.@*
+(print_stack_frame)
+@end deftypefun
+
+
+@deftypefun void gdb_print_backtrace (cback, @var{count}, @var{from_tty})
+@example
+struct gdb_stream_cback * @var{cback};
+int @var{count};
+int @var{from_tty};
+@end example
+Print briefly all stack frames or just the innermost @var{count} frames.@*
+(backtrace_command)
+@end deftypefun
+
+
+@deftypefun FRAME gdb_find_relative_frame (FRAME @var{frame}, int * @var{level_offset_ptr})
+Find a frame a certain number of levels away from @var{frame}.
+@var{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 @var{*level_offset_ptr} is nonzero and indicates
+how much farther the original request asked to go.
+@end deftypefun
+
+
+@deftypefun FRAME gdb_select_frame_downward (int @var{count})
+@deftypefunx FRAME gdb_select_frame_upward (int @var{count})
+Simply a combination of find_relative_frame and select_frame.
+Returns the newly selected frame.@*
+(down_silently_command, up_silently_command)
+@end deftypefun
+
+
+@deftypefun void gdb_frame_info (struct gdb_stream_cback * @var{cback}, FRAME @var{frame})
+Print verbosely the selected the argument @var{frame}.
+This means absolutely all information in the frame is printed.@*
+(frame_info)
+@end deftypefun
+
+
+@node Expressions, Values, Stack, top
+@comment node-name, next, previous, up
+@chapter How to Parse and Evaluate Expressions
+@cindex parsing
+@cindex expressions
+@cindex {expression evaluation}
+@cindex evaluation
+
+
+@deftp Type {struct expression *}
+This represents a parsed expression as might be used for a
+breakpoint condition.
+@end deftp
+
+
+@deftp Type {struct block}
+Describes a lexical environment.
+@end deftp
+
+See also `Values'
+See also `Examining'
+
+
+@deftypefun struct expression * parse_exp_1 (char ** @var{stringptr}, struct block * @var{block} int @var{comma})
+Read an expression from the string @code{*@var{stringptr}} points to,
+parse it, and return a pointer to a struct expression that we malloc.
+Use @var{block} as the lexical context for variable names;
+if @var{block} is zero, use the block of the selected stack frame.
+Meanwhile, advance @code{*@var{stringptr}} to point after the expression,
+at the first nonwhite character that is not part of the expression
+(possibly a null character).
+
+If @var{comma} is nonzero, stop if a comma is reached.
+(See `Stack' for information about the selected frame)
+@end deftypefun
+
+
+@deftypefun gdb_error_t gdb_evaluate_expression (value * @var{value_out}, struct expression * @var{exp})
+Evaluate an expression. See `values' for more information about
+the return type.@*
+(evaluate_expression)
+@end deftypefun
+
+
+@deftypefun value gdb_evaluate_type (struct expression @var{*exp})
+Evaluate an expression, avoiding all memory references
+and getting a value whose type alone is correct.@*
+(evaluate_type)
+@end deftypefun
+
+
+
+@node Values, Examining, Expressions, top
+@comment node-name, next, previous, up
+@chapter Data from the Inferior, the Values of Expressions
+@cindex values
+@cindex {expression values}
+
+Values are allocated by functions such as @code{gdb_evaluate_expression}.
+All currently allocated values are on the list @code{all_values} and can be
+freed by calling @code{gdb_free_all_values}.
+
+To preserve a value across calls to @code{gdb_free_all_values}, use
+@code{gdb_release_value}. Values added to the history list are automaticly
+released. To free a released value use @code{gdb_free_value}.
+
+
+@deftypefun void gdb_free_value (value)
+Free the memory associated with a released value.
+Do not call this function except on values that have been
+passed to @code{gdb_release_value}.@*
+(gdb_value_free)
+@end deftypefun
+
+
+@deftypefun void gdb_free_all_values (void)
+Free all allocated values which haven't been released.
+This should be called periodically from outside the dynamic
+scope of libgdb functions.@*
+(free_all_values)
+@end deftypefun
+
+
+@deftypefun void gdb_release_value (value @var{val})
+Remove a value from the list @code{all_values} in order to
+protect it from @code{gdb_free_all_values}.@*
+(release_value)
+@end deftypefun
+
+
+There is a `history list' -- a numbered list of values for
+future reference. These can be referred to in expressions,
+for example.
+
+@deftypefun int gdb_record_latest_value (value @var{val})
+Add a value to the history list.@*
+(record_latest_value)
+@end deftypefun
+
+
+@deftypefun value gdb_access_value_history (int @var{index})
+Retrieve a value from the history list.@*
+(access_value_history)
+@end deftypefun
+
+
+[[[At the moment, the only libgdb use for values is
+ string formatting (see `Examining'). So, they are treated
+ as opaque. It'd be useful to expose more of them in the long run.]]]
+
+
+@node Examining, Types, Values, top
+@comment node-name, next, previous, up
+@chapter Formatting Values as Strings
+@cindex examining
+@cindex printing
+@cindex formatting
+@cindex {pretty printing}
+
+
+Many functions in this section use @code{struct gdb_stream_cback}.
+That structure is explained in `Basics'.
+
+
+@deftypefun void gdb_print_formatted (struct gdb_stream_cback * @var{cback}, value @var{val}, int @var{format}, int @var{size})
+Print value @var{val} on a stream according to @var{format}, a letter or 0.
+Do not end with a newline.
+0 means print @var{val} according to its own type.
+@var{size} is the letter for the size of datum being printed.
+This is used to pad hex numbers so they line up.@*
+(print_formatted)
+@end deftypefun
+
+
+@deftypefun static void gdb_printf_command (struct gdb_stream_cback * @var{cback}, char * @var{format}, value * @var{values}, int @var{n_values})@*
+(printf_command)
+@end deftypefun
+
+
+@deftypefun int gdb_value_print (struct gdb_stream_cback * @var{cback}, @var{value}, int @var{format}, enum @var{val_prettyprint})
+Print the value @var{val} in C-ish syntax on @var{stream}.
+@var{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.
+[[[implementation: watch the change in argument order]]]@*
+(value_print)
+@end deftypefun
+
+
+ -- IDIOM: This prints the values of all convenience variables:
+@example
+for (var = internalvars; var; var = var->next)
+@{
+printf_filtered ("$%s = ", var->name);
+value_print (var->value, stdout, 0, Val_pretty_default);
+printf_filtered ("\n");
+@}
+@end example
+
+
+@deftypefun int gdb_print_insn (struct gdb_stream_cback * @var{cback}, CORE_ADDR @var{memaddr})
+Print the instruction at @var{memaddr} and return the
+length of the instruction in bytes.@*
+(print_insn)
+@end deftypefun
+
+
+@deftypefun void gdb_print_address (struct gdb_stream_cback * @var{cback}, CORE_ADDR @var{addr})
+Print address @var{addr} symbolically on @var{stream}.
+First print it as a number. Then perhaps print
+@code{<SYMBOL + OFFSET>} after the number.@*
+(print_address)
+@end deftypefun
+
+
+ -- IDIOM: This is the core of a dissasemble command:
+@example
+for (pc = low; pc < high; )
+@{
+ print_address (pc, stdout);
+ printf_filtered (":\t");
+ pc += print_insn (pc, stdout);
+ printf_filtered ("\n");
+@}
+@end example
+Advice for computing pc extents like @code{low} and @code{high}
+can be found in `Symtabs' -- for example, @code{gdb_find_line_pc_range}.@*
+(disassemble_command)
+
+
+@deftypefun void gdb_print_registers (struct gdb_stream_cback * @var{cback}, int @var{regnum}, int @var{fpregs}, int @var{fancy})
+Print the values of registers.
+@var{regnum} can be -1 (print all the registers) or a specific register number.
+If @var{regnum} is -1, @var{fpregs} determines whether floating point registers are
+shown.@*
+(info registers, info all-registers, nofp_registers_info, all_registers_info)
+@end deftypefun
+
+
+@deftypefun char * gdb_register_name (int @var{i})
+Look up a register name by number.
+@end deftypefun
+
+
+@deftypefun int gdb_parse_register_name (char ** @var{name})
+Parse a register name and advance a text pointer.
+Return -1 for bogus names.
+@end deftypefun
+
+
+@deftypefun CORE_ADDR gdb_read_pc ()
+Return the contents of the inferior's program counter.
+@end deftypefun
+
+
+@deftypefun int gdb_is_stepping ()
+If true, the inferior is stopped after being stepped.
+@end deftypefun
+
+
+@deftypefun void gdb_current_breakpoints (gdb_int_cback)
+Call a callback for each of the current breakpoints.@*
+(program_info)
+@end deftypefun
+
+
+@deftypefun int gdb_stop_signal ()
+Return the signal that stopped the inferior.
+@end deftypefun
+
+
+@deftypefun char * strsigno (int)
+Return a symbolic name for a signal.
+@end deftypefun
+
+
+@deftypefun void gdb_target_info (struct gdb_stream_cback *)
+Print status information about target we're accessing.@*
+(target_files_info, e.g. child_files_info)
+@end deftypefun
+
+
+float_info
+[[[what is appropriate?]]]
+
+
+@deftypefun void gdb_address_info (struct gdb_stream_cback * @var{cback}, char * @var{symbol});
+Like the `info address' command -- show where @var{symbol}
+is located.@*
+(address_info)
+@end deftypefun
+
+
+@node Types, top, Examining, top
+@comment node-name, next, previous, up
+@chapter Examining the Types of an Inferior's Data
+@cindex types
+
+
+@deftp Type {struct type}
+@code{struct type *} is used to represent a type. For example, that is
+the type returned by the macro @code{VALUE_TYPE(val)} which yields the
+type of inferior data recorded in @code{val}. (see `evaluate_type' in
+`Expressions').
+@end deftp
+
+
+@deftypefun void type_print (@var{type}, @var{varstring}, @var{stream_cback}, @var{show})
+@example
+struct type @var{*type};
+char @var{*varstring};
+struct gdb_stream_cback * @var{stream_cback};
+FILE @var{*stream};
+int @var{show};
+@end example
+Print a description of a type @var{type} in the form of a declaration of a
+variable named @var{varstring}. (@var{varstring} is demangled if necessary.)
+Output goes to @var{stream_cback}.
+
+If @var{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 @var{show} is negative, we never show the details of elements' types.
+(See `Basics' for an explanation of `struct gdb_stream_cback').
+@end deftypefun
+
+
+[[[In the long run, we need something to programmaticly read off type
+ structures in a machine/language independent way.]]]
+
+@bye
diff --git a/gnu/usr.bin/gdb/doc/lpsrc.sed b/gnu/usr.bin/gdb/doc/lpsrc.sed
new file mode 100644
index 000000000000..1c7af4aaf48f
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/lpsrc.sed
@@ -0,0 +1,13 @@
+/font defs: ---/,/end font defs ---/c\
+%-------------------- PostScript (long names) font defs: -----------------\
+\\font\\bbf=Times-Bold at 10pt\
+\\font\\vbbf=Times-Bold at 12pt\
+\\font\\smrm=Times-Roman at 6pt\
+\\font\\brm=Times-Roman at 10pt\
+\\font\\rm=Times-Roman at 8pt\
+\\font\\it=Times-Italic at 8pt\
+\\font\\tt=Courier at 8pt\
+% Used only for \copyright, replacing plain TeX macro.\
+\\font\\sym=Symbol at 7pt\
+\\def\\copyright{{\\sym\\char'323}}\
+%-------------------- end font defs ---------------------------------
diff --git a/gnu/usr.bin/gdb/doc/psrc.sed b/gnu/usr.bin/gdb/doc/psrc.sed
new file mode 100644
index 000000000000..9bb557eae21e
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/psrc.sed
@@ -0,0 +1,13 @@
+/font defs: ---/,/end font defs ---/c\
+%-------------------- PostScript (K Berry names) font defs: --------------\
+\\font\\bbf=ptmb at 10pt\
+\\font\\vbbf=ptmb at 12pt\
+\\font\\smrm=ptmr at 6pt\
+\\font\\brm=ptmr at 10pt\
+\\font\\rm=ptmr at 8pt\
+\\font\\it=ptmri at 8pt\
+\\font\\tt=pcrr at 8pt\
+% Used only for \copyright, replacing plain TeX macro.\
+\\font\\sym=psyr at 7pt\
+\\def\\copyright{{\\sym\\char'323}}\
+%-------------------- end font defs ---------------------------------
diff --git a/gnu/usr.bin/gdb/doc/refcard.ps b/gnu/usr.bin/gdb/doc/refcard.ps
new file mode 100644
index 000000000000..0046b795faf3
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/refcard.ps
@@ -0,0 +1,798 @@
+%!PS-Adobe-2.0
+%%Creator: dvips 5.47 Copyright 1986-91 Radical Eye Software
+%%Title: refcard.dvi
+%%Pages: 2 1
+%%BoundingBox: 0 0 612 792
+%%EndComments
+%%BeginProcSet: tex.pro
+/TeXDict 200 dict def TeXDict begin /N /def load def /B{bind def}N /S /exch
+load def /X{S N}B /TR /translate load N /isls false N /vsize 10 N /@rigin{
+isls{[0 1 -1 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale
+Resolution VResolution vsize neg mul TR matrix currentmatrix dup dup 4 get
+round 4 exch put dup dup 5 get round 5 exch put setmatrix}N /@letter{/vsize 10
+N}B /@landscape{/isls true N /vsize -1 N}B /@a4{/vsize 10.6929133858 N}B /@a3{
+/vsize 15.5531 N}B /@ledger{/vsize 16 N}B /@legal{/vsize 13 N}B /@manualfeed{
+statusdict /manualfeed true put}B /@copies{/#copies X}B /FMat[1 0 0 -1 0 0]N
+/FBB[0 0 0 0]N /nn 0 N /IE 0 N /ctr 0 N /df-tail{/nn 8 dict N nn begin
+/FontType 3 N /FontMatrix fntrx N /FontBBox FBB N string /base X array
+/BitMaps X /BuildChar{CharBuilder}N /Encoding IE N end dup{/foo setfont}2
+array copy cvx N load 0 nn put /ctr 0 N[}B /df{/sf 1 N /fntrx FMat N df-tail}
+B /dfs{div /sf X /fntrx[sf 0 0 sf neg 0 0]N df-tail}B /E{pop nn dup definefont
+setfont}B /ch-width{ch-data dup length 5 sub get}B /ch-height{ch-data dup
+length 4 sub get}B /ch-xoff{128 ch-data dup length 3 sub get sub}B /ch-yoff{
+ch-data dup length 2 sub get 127 sub}B /ch-dx{ch-data dup length 1 sub get}B
+/ch-image{ch-data dup type /stringtype ne{ctr get /ctr ctr 1 add N}if}B /id 0
+N /rw 0 N /rc 0 N /gp 0 N /cp 0 N /G 0 N /sf 0 N /CharBuilder{save 3 1 roll S
+dup /base get 2 index get S /BitMaps get S get /ch-data X pop /ctr 0 N ch-dx 0
+ch-xoff ch-yoff ch-height sub ch-xoff ch-width add ch-yoff setcachedevice
+ch-width ch-height true[1 0 0 -1 -.1 ch-xoff sub ch-yoff .1 add]{ch-image}
+imagemask restore}B /D{/cc X dup type /stringtype ne{]}if nn /base get cc ctr
+put nn /BitMaps get S ctr S sf 1 ne{dup dup length 1 sub dup 2 index S get sf
+div put}if put /ctr ctr 1 add N}B /I{cc 1 add D}B /bop{userdict /bop-hook
+known{bop-hook}if /SI save N @rigin 0 0 moveto}N /eop{clear SI restore
+showpage userdict /eop-hook known{eop-hook}if}N /@start{userdict /start-hook
+known{start-hook}if /VResolution X /Resolution X 1000 div /DVImag X /IE 256
+array N 0 1 255{IE S 1 string dup 0 3 index put cvn put}for}N /p /show load N
+/RMat[1 0 0 -1 0 0]N /BDot 260 string N /rulex 0 N /ruley 0 N /v{/ruley X
+/rulex X V}B /V statusdict begin /product where{pop product dup length 7 ge{0
+7 getinterval(Display)eq}{pop false}ifelse}{false}ifelse end{{gsave TR -.1 -.1
+TR 1 1 scale rulex ruley false RMat{BDot}imagemask grestore}}{{gsave TR -.1
+-.1 TR rulex ruley scale 1 1 false RMat{BDot}imagemask grestore}}ifelse B /a{
+moveto}B /delta 0 N /tail{dup /delta X 0 rmoveto}B /M{S p delta add tail}B /b{
+S p tail}B /c{-4 M}B /d{-3 M}B /e{-2 M}B /f{-1 M}B /g{0 M}B /h{1 M}B /i{2 M}B
+/j{3 M}B /k{4 M}B /w{0 rmoveto}B /l{p -4 w}B /m{p -3 w}B /n{p -2 w}B /o{p -1 w
+}B /q{p 1 w}B /r{p 2 w}B /s{p 3 w}B /t{p 4 w}B /x{0 S rmoveto}B /y{3 2 roll p
+a}B /bos{/SS save N}B /eos{clear SS restore}B end
+%%EndProcSet
+TeXDict begin 1000 300 300 @start /Fa 3 104 df<0003FE0000000FFF8000003C01E000
+00F000780001C0001C00030000060006000003000C0000018018000000C018000000C030000000
+603000000060600000003060000000306000000030C000000018C000000018C000000018C00000
+0018C000000018C000000018C000000018C000000018C000000018600000003060000000306000
+0000303000000060300000006018000000C018000000C00C000001800600000300030000060001
+C0001C0000F0007800003C01E000000FFF80000003FE000025277E9D2A>13
+D<003C00E001C00180038003800380038003800380038003800380038003800380038003000700
+1C00F0001C00070003000380038003800380038003800380038003800380038003800380018001
+C000E0003C0E297D9E15>102 D<F0001C00070003000380038003800380038003800380038003
+800380038003800380018001C000E0003C00E001C0018003800380038003800380038003800380
+03800380038003800380030007001C00F0000E297D9E15>I E /Fb 1 59
+df<60F0F06004047C830C>58 D E /Fc 61 125 df<01F8000604000C0E00180E001800001800
+00180000FFFE001806001806001806001806001806001806001806001806001806001806001806
+007E1F801114809313>12 D<01FE00060E000C0E00180600180600180600180600FFFE00180600
+1806001806001806001806001806001806001806001806001806001806007E1F801114809313>
+I<4100E380618020802080208041004100820009097F9311>34 D<020002000F8032406220C210
+C270C270E220F2007F003FC00FE002E002704230E230C2308220426022C01F00020002000C187E
+9511>36 D<40E06020202040408003097D9309>39 D<01020408103020606040C0C0C0C0C0C0C0
+C0C0C040606020301008040201081E7E950D>I<80402010080C04060602030303030303030303
+03020606040C0810204080081E7E950D>I<006000006000006000006000006000006000006000
+006000006000006000FFFFF0FFFFF0006000006000006000006000006000006000006000006000
+00600000600014167E9119>43 D<40E06020202040408003097D8209>I<FFFF080280860B>I<40
+E04003037D8209>I<0010003000600060006000C000C000C00180018003000300030006000600
+06000C000C000C0018001800300030003000600060006000C000C0000C1D7E9511>I<0F0030C0
+606060604020C030C030C030C030C030C030C030C030C03040206060606030C00F000C137E9211
+>I<0C001C00EC000C000C000C000C000C000C000C000C000C000C000C000C000C000C000C00FF
+C00A137D9211>I<1F0060C06060F070F030603000700070006000C001C0018002000400081010
+1020207FE0FFE00C137E9211>I<40E0400000000000000040E040030D7D8C09>58
+D<40E0400000000000000040E06020202040408003137D8C09>I<003000003000007800007800
+007800009C00009C00011E00010E00010E0002070002070004038007FF800403800801C00801C0
+1000E03800E0FE07FC16147F9319>65 D<FFFC001C07001C03801C01C01C01C01C01C01C01C01C
+03801C07001FFE001C03801C01C01C00E01C00E01C00E01C00E01C00E01C01C01C0380FFFE0013
+147F9317>I<00FC200703600C00E0180060300060700020600020E00000E00000E00000E00000
+E00000E000006000207000203000201800400C008007030000FC0013147E9318>I<FFFC001C07
+001C01C01C00E01C00601C00701C00301C00381C00381C00381C00381C00381C00381C00301C00
+701C00601C00E01C01C01C0380FFFC0015147F9319>I<FFFF801C03801C00801C00801C00401C
+00401C08401C08001C18001FF8001C18001C08001C08201C00201C00201C00601C00401C00C01C
+01C0FFFFC013147F9316>I<00FC200703600C00E0180060300060700020600020E00000E00000
+E00000E00000E00FF8E000E06000E07000E03000E01800E00C00E007036000FC2015147E931A>
+71 D<FFC0001C00001C00001C00001C00001C00001C00001C00001C00001C00001C00001C0000
+1C00401C00401C00401C00C01C00801C01801C0380FFFF8012147F9315>76
+D<FE000FE01E000F00170017001700170017001700138027001380270011C0470011C0470010E0
+870010E0870010E087001071070010710700103A0700103A0700101C0700101C0700381C0700FE
+083FE01B147F931E>I<FC01FC1E007017002017802013802011C02010E0201070201070201038
+20101C20100E20100F201007201003A01001E01000E01000E0380060FE002016147F9319>I<01
+F800070E001C03803801C03000C07000E0600060E00070E00070E00070E00070E00070E0007070
+00E07000E03000C03801C01C0380070E0001F80014147E9319>I<FFFC001C07001C03801C01C0
+1C01C01C01C01C01C01C01C01C03801C07001FFC001C00001C00001C00001C00001C00001C0000
+1C00001C0000FF800012147F9316>I<FFF8001C07001C03801C01C01C01C01C01C01C01C01C03
+801C07001FF8001C0E001C07001C03801C03801C03801C03801C03841C03841C01CCFF80F81614
+7F9318>82 D<7FFFF0607030407010407010807008807008807008007000007000007000007000
+00700000700000700000700000700000700000700000700007FF0015147F9318>84
+D<FF81FC1C00701C00201C00201C00201C00201C00201C00201C00201C00201C00201C00201C00
+201C00201C00200C00200E004006008003830000FC0016147F9319>I<FF1FF0FC380380303803
+80301C03C0201C03C0201E03C0600E04E0400E04E0400704E08007087080070870800388710003
+9039000390390001F03E0001E01E0001E01E0000C00C0000C00C0000C00C001E147F9321>87
+D<FF00FC3C00301E00200E004007004007808003C10001C10001E20000F6000074000038000038
+0000380000380000380000380000380000380001FF0016147F9319>89 D<208041004100820082
+008200C300E380410009097A9311>92 D<7F00E1C0E0404060006007E038606060C060C064C064
+61E43E380E0D7E8C11>97 D<F00030003000300030003000300033E034103808300C3006300630
+0630063006300C3808343023E00F147F9312>I<0FE0187020706020C000C000C000C000C00060
+00201018200FC00C0D7F8C0F>I<00780018001800180018001800180F98187820386018C018C0
+18C018C018C0186018203810580F9E0F147F9312>I<0F80104020206030C010FFF0C000C000C0
+006000201018200FC00C0D7F8C0F>I<03C00CE018E01840180018001800FF0018001800180018
+0018001800180018001800180018007F000B1480930A>I<0F3C30E62040606060606060204030
+C02F00600060003FE03FF06018C00CC00CC00C601830300FC00F147F8C11>I<F0003000300030
+0030003000300033E034303818301830183018301830183018301830183018FC7E0F147F9312>
+I<2070200000000000F03030303030303030303030FC06157F9409>I<02070200000000000F03
+0303030303030303030303030343E2E67C081B82940A>I<F00030003000300030003000300030
+F8306030403080330037003B80318030C0306030703030FC7C0E147F9311>I<F0303030303030
+303030303030303030303030FC06147F9309>I<F3E1F0343218381C0C30180C30180C30180C30
+180C30180C30180C30180C30180C30180CFC7E3F180D7F8C1B>I<F3E034303818301830183018
+301830183018301830183018FC7E0F0D7F8C12>I<0FC0186020106018C00CC00CC00CC00CC00C
+6018601838700FC00E0D7F8C11>I<F3E034303808300C30063006300630063006300C38083430
+33E030003000300030003000FC000F137F8C12>I<0F88184820386018C018C018C018C018C018
+6018203818580F9800180018001800180018007E0F137F8C11>I<F3C034E038E0304030003000
+300030003000300030003000FE000B0D7F8C0D>I<3E806180C080C080E0007E003F8003C080C0
+80C0C0C0E1809F000A0D7F8C0D>I<10001000100030007000FF80300030003000300030003000
+300030803080308011000E0009127F910D>I<F078301830183018301830183018301830183018
+303818580F9E0F0D7F8C12>I<F87C301830101820182018200C400C4006800680078003000300
+0E0D7F8C11>I<F87CF8707030305820305820188840188C40188C400D04800D06800D06800603
+00060300060300150D7F8C18>I<F87C303018600C400C800700030007800CC008E010603030F8
+7C0E0D7F8C11>I<F87C301830101820182018200C400C400680068007800300030002000200E6
+00E400E80070000E137F8C11>I<FFF0C06080C081C08180030006000C101810383030206060FF
+E00C0D7F8C0F>I<FFFFFFFF2001808821>124 D E /Fd 2 94 df<FEFEC0C0C0C0C0C0C0C0C0C0
+C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0FEFE07297C9E0C>91
+D<FEFE060606060606060606060606060606060606060606060606060606060606060606060606
+06FEFE0729809E0C>93 D E /Fe 27 123 df<001F8F000020D9800060990000C0300000C03000
+00C0300000C0300007FFFE000180300001806000018060000180600001806000030060000300C0
+000300C0000300C0000300C0000600C00006018000060180000601800004010000CCC30000C8C6
+000070780000191A819315>11 D<000FF000301800601000600000C00000C00000C00007FFE000
+C0600180600180C00180C00180C00180C00181800301900301900301900301A00300E006000006
+0000060000C40000C80000700000151A819314>I<FEFC07027D860C>45
+D<000080000180000300000300000600000600000C000018000018000030000030000060000060
+0000C0000180000180000300000300000600000C00000C00001800001800003000003000006000
+00C00000C00000800000111D7E9512>47 D<07C03F8000C00C0001600800016008000120080001
+300800023010000218100002181000020C1000040C200004042000040620000402200008034000
+080340000801C0000801C00018008000FE00800019147E9319>78 D<07B00C7010703060606060
+606060C0C0C0C8C0C841C862D03C700D0D7C8C12>97 D<7C000C00180018001800180030003700
+388030C060C060C060C060C0C180C180C1004300660038000A147C9310>I<07800C4010603040
+600060006000C000C0004020404021801E000B0D7C8C10>I<007C000C00180018001800180030
+07B00C7010703060606060606060C0C0C0C8C0C841C862D03C700E147C9312>I<07800C401020
+304060407F8060004000C0004020604021801E000B0D7C8C10>I<001C00660064006000C000C0
+00C007F800C001800180018001800180030003000300030003000200060006000600C400C80070
+000F1A81930B>I<01D8023804380C3018301830183030603060306010E019C00EC000C000C001
+80C180C3007C000D137E8C10>I<3E0006000C000C000C000C00180019E01E3018303830303030
+3030306060606460C460C4C0C8C0700E147D9312>I<02060000000000384C4C8C981818303262
+62643807147D930B>I<7C0C181818183030303060606060C0D0D0D0D06006147C9309>108
+D<30F878590D8C4E0E0C9C0E0C980C0C180C0C180C0C3018183018193018313018316030326030
+1C180D7D8C1C>I<30F05B184C189C189818181818183030303230623062606460380F0D7D8C13>
+I<03800C6018203030603060306030C060C06040C0608023001E000C0D7C8C12>I<0C78168C13
+0426062606060606060C0C0C0C0C080C101A2019C018001800300030003000FC000F137F8C12>
+I<31F05A184C109C009800180018003000300030003000600060000D0D7D8C0F>114
+D<0700188018C0308038001E001F0003800180C180810082007C000A0D7D8C0E>I<04000C000C
+000C001800FF8018001800300030003000300060006100610062006400380009127D910C>I<38
+184C184C188C3098301830183030603064306430E411E80E380E0D7D8C12>I<38104C384C108C
+10981018101810302030203040304018800F000D0D7D8C10>I<071E09E311C221802180018001
+800300030403044308C51078E0100D7F8C10>120 D<38184C184C188C30983018301830306030
+60306030E011C00EC000C000802180630046003C000D137D8C11>I<06100F2010E00040008001
+0002000C00102020203840478083000C0D7E8C0E>I E /Ff 55 123 df<0100030003000F803F
+E073704338C338C338C31073007F003FC00FE003F003384318E318E318E33073603FC00F800300
+030001000D1A7E9612>36 D<07001F8019C039C039C039C039BE3B3E3E701C701C701CE03EE06F
+E0E7C0E3C4E38E63CE7EFC3C380F147F9312>38 D<070007000700E738FFF87FF01FC01FC07FF0
+FFF8E7380700070007000D0E7E9012>42 D<038003800380038003800380FFFEFFFEFFFE038003
+8003800380038003800F0F7F9112>I<60F0F878183030E0C00509798312>I<FFF8FFF8FFF80D03
+7E8B12>I<60F0F0600404798312>I<0018003800380070007000E000E001C001C001C003800380
+070007000E000E001C001C001C003800380070007000E000E000C0000D1A7E9612>I<07C00FE0
+1C703838701C701CE00EE00EE00EE00EE00EE00EE00EE01E701C701C38381C700FE007C00F147F
+9312>I<0F803FC070E0E070E038E038403800380030007000E000C00180030006000C00183830
+387FF87FF80D147E9312>50 D<0FE03FF07838701C201C001C0038007807E007F00038001C000E
+000E400EE00EE01C78383FF00FC00F147F9312>I<E000FFFEFFFEE018E038007000E000C001C0
+0380038007000700070007000E000E000E000E000E0004000F157F9412>55
+D<60F0F06000000000000060F0F060040E798D12>58 D<0038007801F003E00F801F003C00F800
+F000F8003C001F000F8003E001F0007800380D117E9212>60 D<FFFEFFFE7FFE0000000000007F
+FEFFFEFFFE0F097F8E12>I<4000E000F0007C003E000F8007C001E000F8007800F801E007C00F
+803E007C00F000E00040000D137E9312>I<03E007F01E18381C30FC71FE739EE30EE70EE70EE7
+0EE70EE30C739C71F830F038001E0E07FE03F80F147F9312>64 D<03E60FFE1C3E381E700E700E
+600EE000E000E000E000E000E000600E700E700E381C1C380FF003E00F147F9312>67
+D<FFFEFFFE380E380E380E3800380038E038E03FE03FE038E038E03800380E380E380E380EFFFE
+FFFE0F147F9312>69 D<FFFEFFFE380E380E380E3800380038E038E03FE03FE038E038E0380038
+00380038003800FF00FF000F147F9312>I<FFE0FFE00E000E000E000E000E000E000E000E000E
+000E000E000E000E000E000E000E00FFE0FFE00B147D9312>73 D<FC7EFC7E7C7C745C76DC76DC
+76DC76DC76DC76DC77DC739C739C701C701C701C701C701CF83EF83E0F147F9312>77
+D<FEFEFEFE3E383A383B383B383B383B383B383B3839B839B839B839B839B839B838B838F8FEF8
+FEF80F147F9312>I<3FE07FF07070E038E038E038E038E038E038E038E038E038E038E038E038
+E038E03870707FF03FE00D147E9312>I<FFE0FFF8383C381C380E380E380E380E381C383C3FF8
+3FE0380038003800380038003800FE00FE000F147F9312>I<FF80FFE038F03878383838383838
+387838F03FE03FC038E0387038703870387038773877FE3EFE1C10147F9312>82
+D<1F303FF070F0E070E070E070E00070007F003FC00FE000F0003800386038E038E030F070FFE0
+CF800D147E9312>I<7FFEFFFEE38EE38EE38E0380038003800380038003800380038003800380
+0380038003801FF01FF00F147F9312>I<FE3F80FE3F80380E00380E00380E00380E00380E0038
+0E00380E00380E00380E00380E00380E00380E00380E00380E001C1C000E380007F00003E00011
+14809312>I<3F807FC070E0207000700FF03FF07870E070E070E07070F03FFE1F3E0F0E7E8D12>
+97 D<F800F80038003800380038003BE03FF03C38381C380C380E380E380E380E380C381C3C38
+3FF01BC00F147F9312>I<07F01FF8383870106000E000E000E000E0006000703838381FF007E0
+0D0E7E8D12>I<00F800F8003800380038003807B81FF8387870386038E038E038E038E0386038
+707838781FFE0FBE0F147F9312>I<07801FE0387070706038E038FFF8FFF8E000600070383838
+1FF007C00D0E7E8D12>I<007E00FF01C70382038003807FFEFFFE038003800380038003800380
+03800380038003803FF83FF81014809312>I<0F9E1FFF38E7707070707070707038E03FC03F80
+70003FE03FF83FFC701EE00EE00EE00E600C783C1FF00FE010167F8D12>I<F800F80038003800
+3800380039E03FF03E383C3838383838383838383838383838383838FE3EFE3E0F147F9312>I<
+06000F000F000600000000000000FF00FF000700070007000700070007000700070007000700FF
+F0FFF00C157D9412>I<00C001E001E000C00000000000001FE01FE000E000E000E000E000E000
+E000E000E000E000E000E000E000E000E000E040C0E1C0FF807E000B1C7E9412>I<F800F80038
+003800380038003BFC3BFC38F039E03BC03F803F803FC03DE038E038703838FC7EFC7E0F147F93
+12>I<FF00FF000700070007000700070007000700070007000700070007000700070007000700
+FFF8FFF80D147E9312>I<F71C00FFBE0079E70079E70071C70071C70071C70071C70071C70071
+C70071C70071C700F9E780F8E380110E808D12>I<F9E0FFF03E383C3838383838383838383838
+383838383838FE3EFE3E0F0E7F8D12>I<0F803FE038E07070E038E038E038E038E038F0787070
+38E03FE00F800D0E7E8D12>I<FBE0FFF03C38381C380C380E380E380E380E380C381C3C383FF0
+3BC038003800380038003800FE00FE000F157F8D12>I<079C1FFC387C703C601CE01CE01CE01C
+E01C601C703C387C1FFC079C001C001C001C001C001C007F007F10157F8D12>I<FCF8FDFC1F1C
+1E081E001C001C001C001C001C001C001C00FFC0FFC00E0E7E8D12>I<1FF03FF06070C070E000
+7F003FE00FF000786018E018F030FFE0DFC00D0E7E8D12>I<06000E000E000E007FF8FFF80E00
+0E000E000E000E000E000E000E380E380E3807F003C00D127F9112>I<F8F8F8F8383838383838
+38383838383838383838383838781FFE0FBE0F0E7F8D12>I<FC7EFC7E38383C781C701C701C70
+0EE00EE00EE006C007C007C003800F0E7F8D12>I<FEFEFEFE701C701C301838383BB83FF83FF8
+3AB838B81CF01CF01CF00F0E7F8D12>I<7C7C7C7C1CF00EE00FC007C00380078007C00EE01EF0
+1C70FC7EFC7E0F0E7F8D12>I<FC7EFC7E3C381C381C701C700E700E600E6006E006E003C003C0
+03C0038003800380778077007E003C000F157F8D12>I<3FFC7FFC7038707000E001C003800700
+0E001C1C381C701CFFFCFFFC0E0E7F8D12>I E /Fg 35 122 df<00038000000380000007C000
+0007C0000007C000000FE000000FE000001FF000001BF000001BF0000031F8000031F8000061FC
+000060FC0000E0FE0000C07E0000C07E0001803F0001FFFF0003FFFF8003001F8003001F800600
+0FC006000FC00E000FE00C0007E0FFC07FFEFFC07FFE1F1C7E9B24>65 D<FFFFF800FFFFFF000F
+C01F800FC00FC00FC007C00FC007E00FC007E00FC007E00FC007E00FC007E00FC007C00FC00F80
+0FC03F000FFFFE000FC00F800FC007C00FC007E00FC003E00FC003F00FC003F00FC003F00FC003
+F00FC003F00FC007E00FC007E00FC01FC0FFFFFF00FFFFFC001C1C7E9B22>I<001FE02000FFF8
+E003F80FE007C003E00F8001E01F0000E03E0000E03E0000607E0000607C000060FC000000FC00
+0000FC000000FC000000FC000000FC000000FC000000FC0000007C0000607E0000603E0000603E
+0000C01F0000C00F80018007C0030003F80E0000FFFC00001FE0001B1C7D9B22>I<FFFFF800FF
+FFFF000FC01FC00FC007E00FC001F00FC001F80FC000F80FC000FC0FC0007C0FC0007C0FC0007E
+0FC0007E0FC0007E0FC0007E0FC0007E0FC0007E0FC0007E0FC0007E0FC0007C0FC0007C0FC000
+7C0FC000F80FC000F80FC001F00FC007E00FC01FC0FFFFFF00FFFFF8001F1C7E9B25>I<FFFFFF
+00FFFFFF000FC01F000FC007000FC003000FC003800FC003800FC181800FC181800FC181800FC1
+80000FC380000FFF80000FFF80000FC380000FC180000FC180000FC180600FC180600FC000E00F
+C000C00FC000C00FC001C00FC001C00FC003C00FC00F80FFFFFF80FFFFFF801B1C7E9B1F>I<FF
+FFFF00FFFFFF000FC01F000FC007000FC003000FC003800FC003800FC001800FC181800FC18180
+0FC180000FC180000FC380000FFF80000FFF80000FC380000FC180000FC180000FC180000FC180
+000FC000000FC000000FC000000FC000000FC000000FC00000FFFF0000FFFF0000191C7E9B1E>
+I<000FF008007FFE3801FC07F807E001F80F8000781F0000783F0000383E0000387E0000187C00
+0018FC000000FC000000FC000000FC000000FC000000FC000000FC007FFFFC007FFF7C0001F87E
+0001F83E0001F83F0001F81F0001F80F8001F807E001F801FC07F8007FFE78000FF818201C7D9B
+26>I<FFFC3FFFFFFC3FFF0FC003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F0
+0FC003F00FC003F00FC003F00FFFFFF00FFFFFF00FC003F00FC003F00FC003F00FC003F00FC003
+F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F00FC003F0FFFC3FFFFFFC3FFF201C
+7E9B25>I<FFFF00FFFF000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000FC0000F
+C0000FC0000FC0000FC0000FC0000FC0000FC0030FC0030FC0030FC0070FC0070FC0060FC00E0F
+C01E0FC07EFFFFFEFFFFFE181C7E9B1D>76 D<FFE003FFFFE003FF0FF000300FF800300DFC0030
+0CFE00300C7E00300C3F00300C1F80300C1FC0300C0FE0300C07F0300C03F0300C01F8300C01FC
+300C00FE300C007F300C003F300C001FB00C001FF00C000FF00C0007F00C0003F00C0001F00C00
+00F00C0000F0FFC00070FFC00030201C7E9B25>78 D<FFFFF800FFFFFE000FC03F800FC00F800F
+C007C00FC007E00FC007E00FC007E00FC007E00FC007E00FC007C00FC007C00FC00F800FC03F00
+0FFFFC000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000000FC000
+000FC000000FC00000FFFC0000FFFC00001B1C7E9B21>80 D<07F8201FFEE03C07E07801E07000
+E0F000E0F00060F00060F80000FE0000FFE0007FFE003FFF003FFF800FFFC007FFE0007FE00003
+F00001F00000F0C000F0C000F0C000E0E000E0F001C0FC03C0EFFF0083FC00141C7D9B1B>83
+D<7FFFFFE07FFFFFE0781F81E0701F80E0601F8060E01F8070C01F8030C01F8030C01F8030C01F
+8030001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F8000001F800000
+1F8000001F8000001F8000001F8000001F8000001F8000001F800007FFFE0007FFFE001C1C7E9B
+21>I<FFFC03FFFFFC03FF0FC000300FC000300FC000300FC000300FC000300FC000300FC00030
+0FC000300FC000300FC000300FC000300FC000300FC000300FC000300FC000300FC000300FC000
+300FC000300FC0003007C0003007C0006003E000E001F001C000FC0780007FFE00000FF800201C
+7E9B25>I<FFFC7FFE0FFCFFFC7FFE0FFC0FC007E000C00FC007F000C00FE003F001C007E003F0
+018007E007F8018003F007F8030003F007F8030003F80CFC070001F80CFC060001F81CFE060001
+FC187E0E0000FC187E0C0000FC387F0C00007E303F1800007E303F1800007F601FB800003F601F
+B000003FE01FF000003FC00FF000001FC00FE000001FC00FE000000F8007C000000F8007C00000
+0F0003C0000007000380000007000380002E1C7F9B31>87 D<0FF8001C1E003E0F803E07803E07
+C01C07C00007C0007FC007E7C01F07C03C07C07C07C0F807C0F807C0F807C0780BC03E13F80FE1
+F815127F9117>97 D<FF0000FF00001F00001F00001F00001F00001F00001F00001F00001F0000
+1F00001F3F801FE1E01F80701F00781F003C1F003C1F003E1F003E1F003E1F003E1F003E1F003E
+1F003C1F003C1F00781F80701EC1E01C3F00171D7F9C1B>I<03FC000E0E001C1F003C1F00781F
+00780E00F80000F80000F80000F80000F80000F800007800007801803C01801C03000E0E0003F8
+0011127E9115>I<000FF0000FF00001F00001F00001F00001F00001F00001F00001F00001F000
+01F001F9F00F07F01C03F03C01F07801F07801F0F801F0F801F0F801F0F801F0F801F0F801F078
+01F07801F03C01F01C03F00F0FFE03F9FE171D7E9C1B>I<01FC000F07001C03803C01C07801C0
+7801E0F801E0F801E0FFFFE0F80000F80000F800007800007C00603C00601E00C00F038001FC00
+13127F9116>I<03F8F00E0F381E0F381C07303C07803C07803C07803C07801C07001E0F000E0E
+001BF8001000001800001800001FFF001FFFC00FFFE01FFFF07801F8F00078F00078F000787000
+707800F01E03C007FF00151B7F9118>103 D<FF0000FF00001F00001F00001F00001F00001F00
+001F00001F00001F00001F00001F0FC01F31E01F40F01F80F81F80F81F00F81F00F81F00F81F00
+F81F00F81F00F81F00F81F00F81F00F81F00F81F00F8FFE7FFFFE7FF181D7F9C1B>I<1E003F00
+3F003F003F001E00000000000000000000000000FF00FF001F001F001F001F001F001F001F001F
+001F001F001F001F001F001F00FFE0FFE00B1E7F9D0E>I<FF0000FF00001F00001F00001F0000
+1F00001F00001F00001F00001F00001F00001F0FF81F0FF81F03801F07001F0C001F18001F7000
+1FF8001FFC001FBC001F3E001F1F001F0F001F0F801F07C01F03E0FFC7FCFFC7FC161D7F9C19>
+107 D<FF00FF001F001F001F001F001F001F001F001F001F001F001F001F001F001F001F001F00
+1F001F001F001F001F001F001F001F001F00FFE0FFE00B1D7F9C0E>I<FF0FC07E00FF31E18F00
+1F40F207801F80FC07C01F80FC07C01F00F807C01F00F807C01F00F807C01F00F807C01F00F807
+C01F00F807C01F00F807C01F00F807C01F00F807C01F00F807C01F00F807C0FFE7FF3FF8FFE7FF
+3FF825127F9128>I<FF0FC0FF31E01F40F01F80F81F80F81F00F81F00F81F00F81F00F81F00F8
+1F00F81F00F81F00F81F00F81F00F81F00F8FFE7FFFFE7FF18127F911B>I<01FC000F07801C01
+C03C01E07800F07800F0F800F8F800F8F800F8F800F8F800F8F800F87800F07800F03C01E01E03
+C00F078001FC0015127F9118>I<FF3F80FFE1E01F80F01F00781F007C1F003C1F003E1F003E1F
+003E1F003E1F003E1F003E1F003C1F007C1F00781F80F01FC1E01F3F001F00001F00001F00001F
+00001F00001F0000FFE000FFE000171A7F911B>I<FE3E00FE47001E8F801E8F801E8F801F0700
+1F00001F00001F00001F00001F00001F00001F00001F00001F00001F0000FFF000FFF00011127F
+9114>114 D<1FD830786018E018E018F000FF807FE07FF01FF807FC007CC01CC01CE01CE018F8
+30CFC00E127E9113>I<0300030003000300070007000F000F003FFCFFFC1F001F001F001F001F
+001F001F001F001F001F0C1F0C1F0C1F0C0F08079803F00E1A7F9913>I<FF07F8FF07F81F00F8
+1F00F81F00F81F00F81F00F81F00F81F00F81F00F81F00F81F00F81F00F81F00F81F01F80F01F8
+0786FF01F8FF18127F911B>I<FFC7FCFFC7FC1F81800F838007C70003EE0001FC0001F80000F8
+00007C0000FE0001DF00039F00070F800607C00C03E0FF07FCFF07FC16127F9119>120
+D<FFC1FCFFC1FC1F00601F80E00F80C00FC0C007C18007C18003E30003E30001F70001F60000FE
+0000FC0000FC00007800007800003000003000007000706000F86000F8C000F980007300003E00
+00161A7F9119>I E /Fh 47 122 df<020408103020604040C0C0C0C0C0C0C0C0404060203010
+080402071A7F920C>40 D<8040201018080C0404060606060606060604040C081810204080071A
+7E920C>I<40E060202040408003087E8209>44 D<40E04003037E8209>46
+D<0C003C00CC000C000C000C000C000C000C000C000C000C000C000C000C00FF8009107E8F0F>
+49 D<1F00618040C08060C0600060006000C00180030006000C00102020207FC0FFC00B107F8F
+0F>I<1F00218060C060C000C0008001800F00008000400060C060C060804060801F000B107F8F
+0F>I<0300030007000F000B001300330023004300C300FFE003000300030003001FE00B107F8F
+0F>I<1F00318060C0C040C060C060C06040E021E01E600060004060C0608043003E000B107F8F
+0F>57 D<40E040000000000040E060202040408003107E8A09>59 D<03E0000C180010040023C2
+004631004C0D00980C80980C80980C80980C80980C804C0C80463C8023C7001000000C038003FC
+0011117E9017>64 D<FFF8180C18061803180318031806181C1FFC180618031803180318031806
+180EFFF810117F9015>66 D<03F10C0B1807300360014001C000C000C000C000C0004001600130
+0218020C0C03F010117E9016>I<FFF800180C001803001801001801801800801800C01800C018
+00C01800C01800C01800C0180180180100180300180E00FFF80012117F9017>I<FFFE18061802
+180318011821182018601FE01860182018201800180018001800FF0010117F9014>70
+D<03F1000C0B00180700300300600100400100C00000C00000C00000C03FC0C003004003006003
+003003001803000C070003F90012117E9017>I<FF181818181818181818181818181818FF0811
+7F900B>73 D<FF0018001800180018001800180018001800180018021802180218061804181CFF
+FC0F117F9013>76 D<F81FC01C07001C020016020013020013020011820010C20010C200106200
+103200101200101A00100E00100600380600FE020012117F9016>78 D<FFF0181C180418061806
+18061804181C1FF01800180018001800180018001800FF000F117F9014>80
+D<FFE000181800180C00180600180600180600180C001818001FE000181800180C00180C00180C
+00180C00180C20180420FF03C013117F9016>82 D<1F2060E0006080208020800060003E001F80
+00C00060002080208020C040E0C09F000B117E9011>I<7FFF8060C18040C080C0C0C080C04080
+C04000C00000C00000C00000C00000C00000C00000C00000C00000C00000C0000FFC0012117F90
+16>I<FF1FC0180700180200180200180200180200180200180200180200180200180200180200
+1802000802000C040006080001F00012117F9016>I<FC07C03003003003001802001802000C04
+000C040006080006080006080003100003100001A00001A00001E00000C00000C00012117F9016
+>I<3E006300018001800F8031804180C190C19063903DE00C0B7F8A0F>97
+D<F0003000300030003000300037C038603030301830183018301830183030386027800D117F90
+11>I<1F8030C06000C000C000C000C000C000604030801F000A0B7F8A0E>I<01E0006000600060
+006000600F6030E06060C060C060C060C060C060606030E01F780D117F9011>I<1F00318060C0
+C0C0FFC0C000C000C000604030801F000A0B7F8A0E>I<07000D801800180018001800FE001800
+180018001800180018001800180018007E00091180900A>I<1EF0331061806180618033003E00
+400060003F803FC060E0C060C060C06060C01F000C117F8A0F>I<F00030003000300030003000
+33C03C6030603060306030603060306030603060FCF80D117F9011>I<30703000000000F03030
+30303030303030FC0612809108>I<F0003000300030003000300031F030C03080330036003F00
+3300318031C030C0F9F00C117F9010>107 D<F0303030303030303030303030303030FC061180
+9008>I<F3C3C03C2C20383830303030303030303030303030303030303030303030FCFCFC160B
+7F8A1A>I<F3C03C6030603060306030603060306030603060FCF80D0B7F8A11>I<1F00318060C0
+C060C060C060C060C06060C031801F000B0B7F8A0F>I<F7C03860303030183018301830183018
+3030386037803000300030003000FC000D107F8A11>I<F7003980300030003000300030003000
+30003000FC00090B7F8A0C>114 D<3E028280783E038181C2BC080B7F8A0C>I<10103030FE3030
+303030323232321C070F7F8E0C>I<F1E03060306030603060306030603060306030E00F780D0B
+7F8A11>I<F8F0706030403040188018800D000D000D00060006000C0B7F8A10>I<F9F3C060E180
+30E10030E1003131001932001A12000E1C000E1C000C0C00040800120B7F8A16>I<F8F0306030
+403040188018800D000D000F000600060004000400CC00C80070000C107F8A10>121
+D E /Fi 12 86 df<FFFFFF8000FFFFFFE00007F001F80007F000FC0007F0007E0007F0007E00
+07F0007F0007F0007F0007F0007F0007F0007F0007F0007F0007F0007E0007F000FE0007F000FC
+0007F003F80007FFFFF00007FFFFF00007F001FC0007F0007E0007F0003F0007F0003F8007F000
+1F8007F0001FC007F0001FC007F0001FC007F0001FC007F0001FC007F0001FC007F0003F8007F0
+003F8007F0007F0007F001FE00FFFFFFF800FFFFFFC00022227EA128>66
+D<0003FE0080001FFF818000FF01E38001F8003F8003E0001F8007C0000F800F800007801F8000
+07803F000003803F000003807F000001807E000001807E00000180FE00000000FE00000000FE00
+000000FE00000000FE00000000FE00000000FE00000000FE000000007E000000007E000001807F
+000001803F000001803F000003801F800003000F8000030007C000060003F0000C0001F8003800
+00FF00F000001FFFC0000003FE000021227DA128>I<FFFFFF8000FFFFFFF00007F003FC0007F0
+007E0007F0003F0007F0001F8007F0000FC007F00007E007F00007E007F00007F007F00003F007
+F00003F007F00003F007F00003F807F00003F807F00003F807F00003F807F00003F807F00003F8
+07F00003F807F00003F807F00003F807F00003F007F00003F007F00003F007F00007E007F00007
+E007F0000FC007F0001F8007F0003F0007F0007E0007F003FC00FFFFFFF000FFFFFF800025227E
+A12B>I<FFFFFFFCFFFFFFFC07F000FC07F0003C07F0001C07F0000C07F0000E07F0000E07F000
+0607F0180607F0180607F0180607F0180007F0380007F0780007FFF80007FFF80007F0780007F0
+380007F0180007F0180007F0180307F0180307F0000307F0000607F0000607F0000607F0000E07
+F0000E07F0001E07F0003E07F001FCFFFFFFFCFFFFFFFC20227EA125>I<FFFFFFF8FFFFFFF807
+F001F807F0007807F0003807F0001807F0001C07F0001C07F0000C07F0000C07F0180C07F0180C
+07F0180007F0180007F0380007F0780007FFF80007FFF80007F0780007F0380007F0180007F018
+0007F0180007F0180007F0000007F0000007F0000007F0000007F0000007F0000007F0000007F0
+0000FFFFE000FFFFE0001E227EA123>I<0003FE0040001FFFC0C0007F00F1C001F8003FC003F0
+000FC007C00007C00FC00003C01F800003C03F000001C03F000001C07F000000C07E000000C07E
+000000C0FE00000000FE00000000FE00000000FE00000000FE00000000FE00000000FE00000000
+FE000FFFFC7E000FFFFC7F00001FC07F00001FC03F00001FC03F00001FC01F80001FC00FC0001F
+C007E0001FC003F0001FC001FC003FC0007F80E7C0001FFFC3C00003FF00C026227DA12C>I<FF
+FFE0FFFFE003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003
+F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003F80003
+F80003F80003F80003F80003F80003F800FFFFE0FFFFE013227FA115>73
+D<FFFF803FFCFFFF803FFC07F000038007F000070007F0000E0007F000180007F000300007F000
+E00007F001C00007F003800007F007000007F00E000007F018000007F038000007F0FC000007F1
+FE000007F3FE000007F77F000007FE7F800007F83F800007F01FC00007F01FE00007F00FE00007
+F007F00007F007F80007F003F80007F001FC0007F001FE0007F000FF0007F0007F0007F0007F80
+07F0003FC0FFFF83FFFCFFFF83FFFC26227EA12C>75 D<FFF8001FFEFFFC001FFE07FC0000C007
+FE0000C006FF0000C0067F8000C0063FC000C0061FE000C0060FE000C0060FF000C00607F800C0
+0603FC00C00601FE00C00600FE00C00600FF00C006007F80C006003FC0C006001FE0C006000FF0
+C0060007F0C0060007F8C0060003FCC0060001FEC0060000FFC00600007FC00600007FC0060000
+3FC00600001FC00600000FC006000007C006000003C006000003C0FFF00001C0FFF00000C02722
+7EA12C>78 D<0007FC0000003FFF800000FC07E00003F001F80007E000FC000FC0007E001F8000
+3F001F80003F003F00001F803F00001F807F00001FC07E00000FC07E00000FC0FE00000FE0FE00
+000FE0FE00000FE0FE00000FE0FE00000FE0FE00000FE0FE00000FE0FE00000FE0FE00000FE07E
+00000FC07F00001FC07F00001FC03F00001F803F81F03F801F83F83F000FC70C7E0007E606FC00
+03F607F80000FF07E000003FFF80000007FF80200000038020000001C020000001E0E0000001FF
+E0000001FFC0000000FFC0000000FFC00000007F800000007F000000001E00232C7DA12A>81
+D<FFFFFE0000FFFFFFC00007F007F00007F001F80007F000FC0007F0007E0007F0007F0007F000
+7F0007F0007F0007F0007F0007F0007F0007F0007F0007F0007E0007F000FC0007F001F80007F0
+07F00007FFFFC00007FFFF800007F00FE00007F007F00007F003F80007F001FC0007F001FC0007
+F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC0007F001FC0607F000FE06
+07F000FF0CFFFF803FF8FFFF800FF027227EA12A>I<FFFF803FFCFFFF803FFC07F000018007F0
+00018007F000018007F000018007F000018007F000018007F000018007F000018007F000018007
+F000018007F000018007F000018007F000018007F000018007F000018007F000018007F0000180
+07F000018007F000018007F000018007F000018007F000018007F000018007F000018003F00003
+0003F800030001F800060000FC000E00007E001C00003F80F800000FFFE0000001FF000026227E
+A12B>85 D E end
+%%EndProlog
+%%BeginSetup
+%%Feature: *Resolution 300
+TeXDict begin @landscape
+%%EndSetup
+%%Page: 1 1
+bop -225 -183 a Fi(GDB)14 b(QUICK)g(REFERENCE)22 b Fh(GDB)14
+b(V)n(ersion)h(4)-225 -91 y Fg(Essen)o(tial)c(Commands)-225
+-45 y Ff(gdb)i Fe(pr)n(o)n(gr)n(am)f Fd([)p Fe(c)n(or)n(e)p
+Fd(])24 b Fc(debug)14 b Fe(pr)n(o)n(gr)n(am)e Fd([)p Fc(using)i(coredump)g
+Fe(c)n(or)n(e)p Fd(])-225 9 y Ff(b)f Fd([)p Fe(\014le)p Ff(:)p
+Fd(])p Fe(function)68 b Fc(set)13 b(breakp)q(oin)o(t)i(at)e
+Fe(function)g Fd([)p Fc(in)h Fe(\014le)p Fd(])-225 63 y Ff(run)f
+Fd([)p Fe(ar)n(glist)p Fd(])126 b Fc(start)13 b(y)o(our)h(program)f
+Fd([)p Fc(with)h Fe(ar)n(glist)p Fd(])-225 106 y Ff(bt)274
+b Fc(bac)o(ktrace:)20 b(displa)o(y)c(program)d(stac)o(k)-225
+143 y Ff(p)g Fe(expr)214 b Fc(displa)o(y)15 b(the)f(v)n(alue)h(of)e(an)h
+(expression)-225 180 y Ff(c)292 b Fc(con)o(tin)o(ue)14 b(running)h(y)o(our)f
+(program)-225 218 y Ff(n)292 b Fc(next)14 b(line,)h(stepping)g(o)o(v)o(er)f
+(function)g(calls)-225 255 y Ff(s)292 b Fc(next)14 b(line,)h(stepping)g(in)o
+(to)f(function)h(calls)-225 352 y Fg(Starting)c(GDB)-225 398
+y Ff(gdb)256 b Fc(start)13 b(GDB,)h(with)g(no)g(debugging)g(\014les)-225
+435 y Ff(gdb)f Fe(pr)n(o)n(gr)n(am)121 b Fc(b)q(egin)14 b(debugging)g
+Fe(pr)n(o)n(gr)n(am)-225 472 y Ff(gdb)f Fe(pr)n(o)n(gr)n(am)f(c)n(or)n(e)48
+b Fc(debug)14 b(coredump)g Fe(c)n(or)n(e)f Fc(pro)q(duced)h(b)o(y)105
+510 y Fe(pr)n(o)n(gr)n(am)-225 548 y Ff(gdb)f(--help)135 b
+Fc(describ)q(e)14 b(command)g(line)g(options)-225 647 y Fg(Stopping)c(GDB)
+-225 692 y Ff(quit)238 b Fc(exit)14 b(GDB;)g(also)g Ff(q)f
+Fc(or)g Ff(EOF)g Fc(\(eg)g Ff(C-d)p Fc(\))-225 734 y Ff(INTERRUPT)148
+b Fc(\(eg)13 b Ff(C-c)p Fc(\))g(terminate)g(curren)o(t)h(command,)h(or)105
+771 y(send)g(to)e(running)i(pro)q(cess)-225 868 y Fg(Getting)c(Help)-225
+914 y Ff(help)238 b Fc(list)14 b(classes)g(of)g(commands)-225
+951 y Ff(help)e Fe(class)155 b Fc(one-line)14 b(descriptions)h(for)f
+(commands)g(in)105 988 y Fe(class)-225 1021 y Ff(help)e Fe(c)n(ommand)83
+b Fc(describ)q(e)14 b Fe(c)n(ommand)-225 1119 y Fg(Executing)e(y)o(our)h
+(Program)-225 1165 y Ff(run)g Fe(ar)n(glist)150 b Fc(start)13
+b(y)o(our)h(program)f(with)i Fe(ar)n(glist)-225 1203 y Ff(run)256
+b Fc(start)13 b(y)o(our)h(program)f(with)i(curren)o(t)f(argumen)o(t)105
+1240 y(list)-225 1273 y Ff(run)f Fb(:)7 b(:)g(:)12 b Ff(<)p
+Fe(inf)h Ff(>)p Fe(outf)32 b Fc(start)13 b(y)o(our)h(program)f(with)i(input,)
+g(output)105 1310 y(redirected)-225 1360 y Ff(kill)238 b Fc(kill)15
+b(running)g(program)-225 1434 y Ff(tty)e Fe(dev)193 b Fc(use)14
+b Fe(dev)f Fc(as)g(stdin)i(and)f(stdout)g(for)g(next)g Ff(run)-225
+1472 y(set)f(args)f Fe(ar)n(glist)66 b Fc(sp)q(ecify)15 b Fe(ar)n(glist)d
+Fc(for)i(next)g Ff(run)-225 1509 y(set)f(args)171 b Fc(sp)q(ecify)15
+b(empt)o(y)f(argumen)o(t)g(list)-225 1546 y Ff(show)e(args)154
+b Fc(displa)o(y)15 b(argumen)o(t)f(list)-225 1621 y Ff(show)e(environment)28
+b Fc(sho)o(w)13 b(all)i(en)o(vironmen)o(t)g(v)n(ariables)-225
+1659 y Ff(show)d(env)h Fe(var)110 b Fc(sho)o(w)13 b(v)n(alue)i(of)f(en)o
+(vironmen)o(t)h(v)n(ariable)f Fe(var)-225 1696 y Ff(set)f(env)g
+Fe(var)f(string)28 b Fc(set)13 b(en)o(vironmen)o(t)j(v)n(ariable)e
+Fe(var)-225 1733 y Ff(unset)e(env)h Fe(var)92 b Fc(remo)o(v)o(e)13
+b Fe(var)g Fc(from)h(en)o(vironmen)o(t)-225 1820 y Fg(Shell)d(Commands)-225
+1866 y Ff(cd)i Fe(dir)217 b Fc(c)o(hange)13 b(w)o(orking)h(directory)g(to)f
+Fe(dir)-225 1903 y Ff(pwd)256 b Fc(Prin)o(t)15 b(w)o(orking)e(directory)-225
+1941 y Ff(make)f Fb(:)7 b(:)g(:)176 b Fc(call)14 b(\\)p Ff(make)p
+Fc(")-225 1978 y Ff(shell)e Fe(cmd)146 b Fc(execute)13 b(arbitrary)h(shell)h
+(command)f(string)-225 2100 y Fd([)f(])h Fh(surround)f(optional)j(argumen)o
+(ts)45 b Fb(:)7 b(:)g(:)13 b Fh(sho)o(w)h(one)f(or)h(more)f(argumen)o(ts)-216
+2174 y(c)-230 2175 y Fa(\015)p Fh(1991,)h(1992)h(F)n(ree)d(Soft)o(w)o(are)h
+(F)n(oundation,)h(Inc.)60 b(P)o(ermissions)15 b(on)f(bac)o(k)p
+800 -217 1 9 v 800 2175 V 875 -183 a Fg(Breakp)q(oin)o(ts)d(and)j(W)l(atc)o
+(hp)q(oin)o(ts)875 -132 y Ff(break)e Fd([)p Fe(\014le)p Ff(:)p
+Fd(])p Fe(line)875 -86 y Ff(b)i Fd([)p Fe(\014le)p Ff(:)p Fd(])p
+Fe(line)1185 -132 y Fc(set)g(breakp)q(oin)o(t)g(at)f Fe(line)h
+Fc(n)o(um)o(b)q(er)h Fd([)p Fc(in)f Fe(\014le)p Fd(])1185 -94
+y Fc(eg:)33 b Ff(break)12 b(main.c:37)875 -32 y(break)g Fd([)p
+Fe(\014le)p Ff(:)p Fd(])p Fe(func)57 b Fc(set)14 b(breakp)q(oin)o(t)g(at)f
+Fe(func)h Fd([)p Fc(in)g Fe(\014le)p Fd(])875 11 y Ff(break)e(+)p
+Fe(o\013set)875 48 y Ff(break)g(-)p Fe(o\013set)1185 11 y Fc(set)i(break)f
+(at)h Fe(o\013set)f Fc(lines)i(from)f(curren)o(t)g(stop)875
+87 y Ff(break)e(*)p Fe(addr)121 b Fc(set)14 b(breakp)q(oin)o(t)g(at)f
+(address)h Fe(addr)875 124 y Ff(break)220 b Fc(set)14 b(breakp)q(oin)o(t)g
+(at)f(next)i(instruction)875 161 y Ff(break)d Fb(:)7 b(:)g(:)12
+b Ff(if)i Fe(expr)31 b Fc(break)14 b(conditionally)h(on)f(nonzero)f
+Fe(expr)875 211 y Ff(cond)g Fe(n)h Fd([)p Fe(expr)p Fd(])103
+b Fc(new)13 b(conditional)i(expression)g(on)e(breakp)q(oin)o(t)1206
+248 y Fe(n)p Fc(;)h(mak)o(e)g(unconditional)h(if)g(no)e Fe(expr)875
+286 y Ff(tbreak)f Fb(:)7 b(:)g(:)140 b Fc(temp)q(orary)13 b(break;)i(disable)
+f(when)g(reac)o(hed)875 324 y Ff(rbreak)e Fe(r)n(e)n(gex)115
+b Fc(break)14 b(on)f(all)i(functions)g(matc)o(hing)f Fe(r)n(e)n(gex)875
+361 y Ff(watch)e Fe(expr)143 b Fc(set)14 b(a)f(w)o(atc)o(hp)q(oin)o(t)h(for)f
+(expression)i Fe(expr)875 398 y Ff(catch)d Fe(x)192 b Fc(break)14
+b(at)f(C++)i(handler)f(for)g(exception)g Fe(x)875 473 y Ff(info)f(break)135
+b Fc(sho)o(w)13 b(de\014ned)i(breakp)q(oin)o(ts)875 511 y Ff(info)e(watch)135
+b Fc(sho)o(w)13 b(de\014ned)i(w)o(atc)o(hp)q(oin)o(ts)875 585
+y Ff(clear)220 b Fc(delete)14 b(breakp)q(oin)o(ts)g(at)g(next)g(instruction)
+875 635 y Ff(clear)e Fd([)p Fe(\014le)p Ff(:)p Fd(])p Fe(fun)73
+b Fc(delete)14 b(breakp)q(oin)o(ts)g(at)g(en)o(try)g(to)f Fe(fun)p
+Fc(\(\))875 688 y Ff(clear)f Fd([)p Fe(\014le)p Ff(:)p Fd(])p
+Fe(line)66 b Fc(delete)14 b(breakp)q(oin)o(ts)g(on)g(source)f(line)875
+742 y Ff(delete)f Fd([)p Fe(n)p Fd(])147 b Fc(delete)14 b(breakp)q(oin)o(ts)g
+Fd([)p Fc(or)f(breakp)q(oin)o(t)i Fe(n)p Fd(])875 823 y Ff(disable)c
+Fd([)p Fe(n)p Fd(])130 b Fc(disable)15 b(breakp)q(oin)o(ts)f
+Fd([)p Fc(or)f(breakp)q(oin)o(t)i Fe(n)p Fd(])875 877 y Ff(enable)d
+Fd([)p Fe(n)p Fd(])147 b Fc(enable)14 b(breakp)q(oin)o(ts)g
+Fd([)p Fc(or)f(breakp)q(oin)o(t)i Fe(n)p Fd(])875 931 y Ff(enable)d(once)g
+Fd([)p Fe(n)p Fd(])63 b Fc(enable)14 b(breakp)q(oin)o(ts)g
+Fd([)p Fc(or)f(breakp)q(oin)o(t)i Fe(n)p Fd(])p Fc(;)1206 969
+y(disable)f(again)g(when)f(reac)o(hed)875 1018 y Ff(enable)f(del)h
+Fd([)p Fe(n)p Fd(])80 b Fc(enable)14 b(breakp)q(oin)o(ts)g
+Fd([)p Fc(or)f(breakp)q(oin)o(t)i Fe(n)p Fd(])p Fc(;)1206 1055
+y(delete)e(when)h(reac)o(hed)875 1105 y Ff(ignore)e Fe(n)i(c)n(ount)76
+b Fc(ignore)13 b(breakp)q(oin)o(t)i Fe(n)p Fc(,)f Fe(c)n(ount)g
+Fc(times)875 1180 y Ff(commands)d Fe(n)946 1217 y Fd([)p Ff(silent)p
+Fd(])946 1255 y Fe(c)n(ommand-list)1185 1180 y Fc(execute)i(GDB)h
+Fe(c)n(ommand-list)e Fc(ev)o(ery)j(time)1206 1217 y(breakp)q(oin)o(t)f
+Fe(n)g Fc(is)g(reac)o(hed.)21 b Fd([)p Ff(silent)1206 1263
+y Fc(suppresses)14 b(default)h(displa)o(y)p Fd(])875 1306 y
+Ff(end)256 b Fc(end)14 b(of)g Fe(c)n(ommand-list)875 1393 y
+Fg(Program)f(Stac)o(k)875 1445 y Ff(backtrace)e Fd([)p Fe(n)p
+Fd(])875 1490 y Ff(bt)i Fd([)p Fe(n)p Fd(])1185 1445 y Fc(prin)o(t)i(trace)e
+(of)g(all)h(frames)g(in)h(stac)o(k;)f(or)f(of)h Fe(n)1206 1482
+y Fc(frames|innermost)g(if)h Fe(n)p Ff(>0)p Fc(,)e(outermost)h(if)1206
+1519 y Fe(n)p Ff(<0)875 1563 y(frame)e Fd([)p Fe(n)p Fd(])165
+b Fc(select)13 b(frame)h(n)o(um)o(b)q(er)h Fe(n)f Fc(or)f(frame)h(at)g
+(address)1206 1600 y Fe(n)p Fc(;)g(if)h(no)e Fe(n)p Fc(,)i(displa)o(y)g
+(curren)o(t)f(frame)875 1639 y Ff(up)f Fe(n)242 b Fc(select)13
+b(frame)h Fe(n)g Fc(frames)g(up)875 1676 y Ff(down)f Fe(n)206
+b Fc(select)13 b(frame)h Fe(n)g Fc(frames)g(do)o(wn)875 1720
+y Ff(info)f(frame)f Fd([)p Fe(addr)p Fd(])30 b Fc(describ)q(e)14
+b(selected)g(frame,)g(or)f(frame)h(at)f Fe(addr)875 1763 y
+Ff(info)g(args)153 b Fc(argumen)o(ts)14 b(of)f(selected)h(frame)875
+1800 y Ff(info)f(locals)117 b Fc(lo)q(cal)13 b(v)n(ariables)i(of)e(selected)h
+(frame)875 1844 y Ff(info)f(reg)f Fd([)p Fe(rn)p Fd(])p Fb(:)7
+b(:)g(:)875 1889 y Ff(info)13 b(all-reg)e Fd([)p Fe(rn)p Fd(])1185
+1844 y Fc(register)i(v)n(alues)i Fd([)p Fc(for)e(regs)g Fe(rn)s
+Fd(])g Fc(in)h(selected)1206 1881 y(frame;)g Ff(all-reg)d Fc(includes)k
+(\015oating)e(p)q(oin)o(t)875 1933 y Ff(info)g(catch)135 b
+Fc(exception)14 b(handlers)h(activ)o(e)e(in)i(selected)f(frame)p
+1900 -217 V 1900 2175 V 1975 -183 a Fg(Execution)f(Con)o(trol)1975
+-138 y Ff(continue)e Fd([)p Fe(c)n(ount)p Fd(])1975 -92 y Ff(c)j
+Fd([)p Fe(c)n(ount)p Fd(])2285 -138 y Fc(con)o(tin)o(ue)g(running;)i(if)e
+Fe(c)n(ount)g Fc(sp)q(eci\014ed,)g(ignore)2306 -100 y(this)g(breakp)q(oin)o
+(t)h(next)f Fe(c)n(ount)g Fc(times)1975 -26 y Ff(step)f Fd([)p
+Fe(c)n(ount)p Fd(])1975 20 y Ff(s)h Fd([)p Fe(c)n(ount)p Fd(])2285
+-26 y Fc(execute)g(un)o(til)h(another)e(line)i(reac)o(hed;)f(rep)q(eat)2306
+12 y Fe(c)n(ount)f Fc(times)i(if)f(sp)q(eci\014ed)1975 74 y
+Ff(stepi)e Fd([)p Fe(c)n(ount)p Fd(])1975 120 y Ff(si)h Fd([)p
+Fe(c)n(ount)p Fd(])2285 74 y Fc(step)h(b)o(y)h(mac)o(hine)f(instructions)h
+(rather)f(than)2306 111 y(source)f(lines)1975 186 y Ff(next)g
+Fd([)p Fe(c)n(ount)p Fd(])1975 232 y Ff(n)h Fd([)p Fe(c)n(ount)p
+Fd(])2285 186 y Fc(execute)g(next)g(line,)h(including)h(an)o(y)e(function)
+2306 223 y(calls)1975 286 y Ff(nexti)e Fd([)p Fe(c)n(ount)p
+Fd(])1975 331 y Ff(ni)h Fd([)p Fe(c)n(ount)p Fd(])2285 286
+y Fc(next)h(mac)o(hine)h(instruction)g(rather)e(than)2306 323
+y(source)g(line)1975 398 y Ff(until)f Fd([)p Fe(lo)n(c)n(ation)p
+Fd(])67 b Fc(run)14 b(un)o(til)i(next)e(instruction)h(\(or)e
+Fe(lo)n(c)n(ation)p Fc(\))1975 441 y Ff(finish)202 b Fc(run)14
+b(un)o(til)i(selected)e(stac)o(k)f(frame)h(returns)1975 484
+y Ff(return)e Fd([)p Fe(expr)p Fd(])101 b Fc(p)q(op)14 b(selected)g(stac)o(k)
+f(frame)h(without)2306 522 y(executing)g Fd([)p Fc(setting)f(return)i(v)n
+(alue)p Fd(])1975 566 y Ff(signal)d Fe(num)125 b Fc(resume)14
+b(execution)g(with)g(signal)h Fe(s)f Fc(\(none)f(if)i Ff(0)p
+Fc(\))1975 604 y Ff(jump)e Fe(line)1975 641 y Ff(jump)g(*)p
+Fe(addr)n(ess)2285 604 y Fc(resume)h(execution)g(at)g(sp)q(eci\014ed)g
+Fe(line)f Fc(n)o(um)o(b)q(er)2306 641 y(or)g Fe(addr)n(ess)1975
+681 y Ff(set)g(var=)p Fe(expr)106 b Fc(ev)n(aluate)14 b Fe(expr)e
+Fc(without)i(displa)o(ying)i(it;)f(use)2306 718 y(for)e(altering)h(program)f
+(v)n(ariables)1975 815 y Fg(Displa)o(y)1975 867 y Ff(print)f
+Fd([)p Ff(/)p Fe(f)6 b Fd(])13 b([)p Fe(expr)p Fd(])1975 913
+y Ff(p)h Fd([)p Ff(/)p Fe(f)5 b Fd(])13 b([)p Fe(expr)p Fd(])2285
+867 y Fc(sho)o(w)h(v)n(alue)g(of)g Fe(expr)e Fd([)p Fc(or)h(last)h(v)n(alue)h
+Ff($)p Fd(])2306 904 y Fc(according)e(to)g(format)h Fe(f)p
+Fc(:)2046 956 y Ff(x)221 b Fc(hexadecimal)2046 993 y Ff(d)g
+Fc(signed)14 b(decimal)2046 1030 y Ff(u)221 b Fc(unsigned)15
+b(decimal)2046 1068 y Ff(o)221 b Fc(o)q(ctal)2046 1105 y Ff(t)g
+Fc(binary)2046 1142 y Ff(a)g Fc(address,)14 b(absolute)g(and)g(relativ)o(e)
+2046 1180 y Ff(c)221 b Fc(c)o(haracter)2046 1217 y Ff(f)g Fc(\015oating)13
+b(p)q(oin)o(t)1975 1266 y Ff(call)g Fd([)p Ff(/)p Fe(f)5 b
+Fd(])13 b Fe(expr)89 b Fc(lik)o(e)15 b Ff(print)d Fc(but)i(do)q(es)g(not)g
+(displa)o(y)h Ff(void)1975 1320 y(x)f Fd([)p Ff(/)p Fe(Nuf)5
+b Fd(])14 b Fe(expr)98 b Fc(examine)14 b(memory)g(at)g(address)g
+Fe(expr)p Fc(;)f(optional)2306 1358 y(format)g(sp)q(ec)h(follo)o(ws)g(slash)
+2011 1396 y Fe(N)249 b Fc(coun)o(t)14 b(of)f(ho)o(w)h(man)o(y)h(units)g(to)e
+(displa)o(y)2011 1433 y Fe(u)256 b Fc(unit)15 b(size;)f(one)g(of)2356
+1471 y Ff(b)f Fc(individual)k(b)o(ytes)2356 1508 y Ff(h)c Fc(halfw)o(ords)h
+(\(t)o(w)o(o)f(b)o(ytes\))2356 1545 y Ff(w)g Fc(w)o(ords)h(\(four)g(b)o
+(ytes\))2356 1583 y Ff(g)f Fc(gian)o(t)h(w)o(ords)f(\(eigh)o(t)h(b)o(ytes\))
+2011 1620 y Fe(f)263 b Fc(prin)o(ting)15 b(format.)21 b(An)o(y)14
+b Ff(print)e Fc(format,)i(or)2356 1657 y Ff(s)f Fc(n)o(ull-terminated)j
+(string)2356 1695 y Ff(i)d Fc(mac)o(hine)h(instructions)1975
+1738 y Ff(disassem)d Fd([)p Fe(addr)p Fd(])62 b Fc(displa)o(y)15
+b(memory)g(as)e(mac)o(hine)h(instructions)1975 1840 y Fg(Automatic)e(Displa)o
+(y)1975 1891 y Ff(display)g Fd([)p Ff(/)p Fe(f)5 b Fd(])13
+b Fe(expr)36 b Fc(sho)o(w)14 b(v)n(alue)g(of)g Fe(expr)e Fc(eac)o(h)i(time)g
+(program)2306 1929 y(stops)g Fd([)p Fc(according)e(to)i(format)f
+Fe(f)6 b Fd(])1975 1972 y Ff(display)184 b Fc(displa)o(y)15
+b(all)g(enabled)f(expressions)h(on)f(list)1975 2014 y Ff(undisplay)d
+Fe(n)118 b Fc(remo)o(v)o(e)14 b(n)o(um)o(b)q(er\(s\))h Fe(n)f
+Fc(from)g(list)h(of)2306 2051 y(automatically)f(displa)o(y)o(ed)h
+(expressions)1975 2091 y Ff(disable)d(disp)g Fe(n)69 b Fc(disable)15
+b(displa)o(y)g(for)f(expression\(s\))h(n)o(um)o(b)q(er)g Fe(n)1975
+2132 y Ff(enable)d(disp)g Fe(n)87 b Fc(enable)14 b(displa)o(y)h(for)f
+(expression\(s\))h(n)o(um)o(b)q(er)g Fe(n)1975 2170 y Ff(info)e(display)99
+b Fc(n)o(um)o(b)q(ered)15 b(list)g(of)e(displa)o(y)j(expressions)p
+eop
+%%Page: 2 2
+bop -225 -183 a Fg(Expressions)-225 -138 y Fe(expr)245 b Fc(an)13
+b(expression)i(in)g(C,)f(C++,)g(or)g(Mo)q(dula-2)105 -100 y(\(including)i
+(function)f(calls\),)f(or:)-225 -60 y Fe(addr)s Ff(@)p Fe(len)176
+b Fc(an)13 b(arra)o(y)h(of)f Fe(len)h Fc(elemen)o(ts)h(b)q(eginning)f(at)105
+-23 y Fe(addr)-225 10 y(\014le)p Ff(::)p Fe(nm)182 b Fc(a)13
+b(v)n(ariable)h(or)g(function)h Fe(nm)e Fc(de\014ned)i(in)f
+Fe(\014le)-225 59 y Fa(f)p Fe(typ)n(e)p Fa(g)p Fe(addr)138
+b Fc(read)13 b(memory)h(at)g Fe(addr)e Fc(as)h(sp)q(eci\014ed)h
+Fe(typ)n(e)-225 105 y Ff($)292 b Fc(most)13 b(recen)o(t)h(displa)o(y)o(ed)i
+(v)n(alue)-225 142 y Ff($)p Fe(n)273 b(n)p Fc(th)14 b(displa)o(y)o(ed)i(v)n
+(alue)-225 179 y Ff($$)274 b Fc(displa)o(y)o(ed)15 b(v)n(alue)g(previous)g
+(to)e($)-225 217 y Ff($$)p Fe(n)255 b(n)p Fc(th)14 b(displa)o(y)o(ed)i(v)n
+(alue)e(bac)o(k)g(from)g($)-225 254 y Ff($)p -205 254 11 2
+v 292 w Fc(last)g(address)g(examined)g(with)h Ff(x)-225 291
+y($)p -205 291 V -193 291 V 292 w Fc(v)n(alue)f(at)g(address)g($)p
+357 291 10 2 v -225 329 a Ff($)p Fe(var)243 b Fc(con)o(v)o(enience)14
+b(v)n(ariable;)h(assign)f(an)o(y)g(v)n(alue)-225 410 y Ff(show)e(values)g
+Fd([)p Fe(n)p Fd(])63 b Fc(sho)o(w)13 b(last)h(10)f(v)n(alues)i
+Fd([)p Fc(or)e(surrounding)i($)p Fe(n)p Fd(])-225 453 y Ff(show)d
+(convenience)28 b Fc(displa)o(y)15 b(all)f(con)o(v)o(enience)h(v)n(ariables)
+-225 550 y Fg(Sym)o(b)q(ol)d(T)l(able)-225 595 y Ff(info)g(address)g
+Fe(s)74 b Fc(sho)o(w)13 b(where)h(sym)o(b)q(ol)h Fe(s)f Fc(is)g(stored)-225
+645 y Ff(info)e(func)h Fd([)p Fe(r)n(e)n(gex)p Fd(])42 b Fc(sho)o(w)13
+b(names,)i(t)o(yp)q(es)f(of)g(de\014ned)g(functions)105 682
+y(\(all,)h(or)e(matc)o(hing)h Fe(r)n(e)n(gex)p Fc(\))-225 733
+y Ff(info)e(var)h Fd([)p Fe(r)n(e)n(gex)p Fd(])60 b Fc(sho)o(w)13
+b(names,)i(t)o(yp)q(es)f(of)g(global)f(v)n(ariables)i(\(all,)105
+770 y(or)f(matc)o(hing)g Fe(r)n(e)n(gex)p Fc(\))-225 821 y
+Ff(whatis)e Fd([)p Fe(expr)p Fd(])-225 867 y Ff(ptype)g Fd([)p
+Fe(expr)p Fd(])85 821 y Fc(sho)o(w)h(data)h(t)o(yp)q(e)g(of)g
+Fe(expr)e Fd([)p Fc(or)h Ff($)p Fd(])g Fc(without)105 858 y(ev)n(aluating;)i
+Ff(ptype)d Fc(giv)o(es)i(more)g(detail)-225 910 y Ff(ptype)e
+Fe(typ)n(e)147 b Fc(describ)q(e)14 b(t)o(yp)q(e,)h(struct,)f(union,)h(or)f
+(en)o(um)-225 1008 y Fg(GDB)f(Scripts)-225 1054 y Ff(source)f
+Fe(script)104 b Fc(read,)14 b(execute)f(GDB)h(commands)g(from)g(\014le)105
+1091 y Fe(script)-225 1147 y Ff(define)e Fe(cmd)-154 1184 y(c)n(ommand-list)
+85 1147 y Fc(create)g(new)i(GDB)g(command)g Fe(cmd)p Fc(;)f(execute)105
+1184 y(script)i(de\014ned)f(b)o(y)h Fe(c)n(ommand-list)-225
+1222 y Ff(end)256 b Fc(end)14 b(of)g Fe(c)n(ommand-list)-225
+1260 y Ff(document)d Fe(cmd)-154 1297 y(help-text)85 1260 y
+Fc(create)h(online)j(do)q(cumen)o(tation)f(for)f(new)h(GDB)105
+1297 y(command)g Fe(cmd)-225 1335 y Ff(end)256 b Fc(end)14
+b(of)g Fe(help-text)-225 1432 y Fg(Signals)-225 1478 y Ff(handle)e
+Fe(signal)h(act)44 b Fc(sp)q(ecify)15 b(GDB)e(actions)h(for)f
+Fe(signal)p Fc(:)-190 1515 y Ff(print)185 b Fc(announce)13
+b(signal)-190 1553 y Ff(noprint)149 b Fc(b)q(e)13 b(silen)o(t)i(for)f(signal)
+-190 1590 y Ff(stop)203 b Fc(halt)14 b(execution)g(on)g(signal)-190
+1627 y Ff(nostop)167 b Fc(do)13 b(not)h(halt)g(execution)-190
+1665 y Ff(pass)203 b Fc(allo)o(w)13 b(y)o(our)h(program)f(to)h(handle)g
+(signal)-190 1702 y Ff(nopass)167 b Fc(do)13 b(not)h(allo)o(w)g(y)o(our)g
+(program)f(to)g(see)h(signal)-225 1739 y Ff(info)e(signals)100
+b Fc(sho)o(w)13 b(table)h(of)g(signals,)h(GDB)e(action)h(for)f(eac)o(h)-225
+1838 y Fg(Debugging)e(T)l(argets)-225 1884 y Ff(target)h Fe(typ)n(e)g(p)n(ar)
+n(am)24 b Fc(connect)13 b(to)g(target)g(mac)o(hine,)i(pro)q(cess,)e(or)h
+(\014le)-225 1921 y Ff(help)e(target)118 b Fc(displa)o(y)15
+b(a)o(v)n(ailable)g(targets)-225 1958 y Ff(attach)d Fe(p)n(ar)n(am)97
+b Fc(connect)13 b(to)g(another)h(pro)q(cess)-225 1996 y Ff(detach)202
+b Fc(release)13 b(target)f(from)i(GDB)g(con)o(trol)p 800 -217
+1 9 v 800 2175 V 875 -183 a Fg(Con)o(trollin)o(g)d(GDB)875
+-138 y Ff(set)i Fe(p)n(ar)n(am)f(value)61 b Fc(set)14 b(one)f(of)h(GDB's)g
+(in)o(ternal)h(parameters)875 -100 y Ff(show)e Fe(p)n(ar)n(am)132
+b Fc(displa)o(y)15 b(curren)o(t)f(setting)g(of)g(parameter)875
+-51 y(P)o(arameters)f(understo)q(o)q(d)h(b)o(y)h Ff(set)e Fc(and)h
+Ff(show)p Fc(:)910 -13 y Ff(complaints)d Fe(limit)i Fc(n)o(um)o(b)q(er)i(of)e
+(messages)h(on)f(un)o(usual)j(sym)o(b)q(ols)910 28 y Ff(confirm)c
+Fe(on/o\013)43 b Fc(enable)14 b(or)f(disable)i(cautionary)f(queries)910
+66 y Ff(editing)e Fe(on/o\013)43 b Fc(con)o(trol)13 b Ff(readline)e
+Fc(command-line)k(editing)910 103 y Ff(height)d Fe(lpp)110
+b Fc(n)o(um)o(b)q(er)15 b(of)e(lines)i(b)q(efore)f(pause)g(in)g(displa)o(y)
+910 145 y Ff(language)d Fe(lang)58 b Fc(Language)12 b(for)h(GDB)h
+(expressions)h(\()p Ff(auto)p Fc(,)e Ff(c)g Fc(or)1206 182
+y Ff(modula-2)p Fc(\))910 222 y Ff(listsize)e Fe(n)101 b Fc(n)o(um)o(b)q(er)
+15 b(of)e(lines)i(sho)o(wn)f(b)o(y)h Ff(list)910 259 y(prompt)d
+Fe(str)114 b Fc(use)14 b Fe(str)f Fc(as)g(GDB)h(prompt)910
+297 y Ff(radix)e Fe(b)n(ase)111 b Fc(o)q(ctal,)13 b(decimal,)i(or)e(hex)i(n)o
+(um)o(b)q(er)1206 334 y(represen)o(tation)910 374 y Ff(verbose)d
+Fe(on/o\013)43 b Fc(con)o(trol)13 b(messages)g(when)h(loading)g(sym)o(b)q
+(ols)910 411 y Ff(width)e Fe(cpl)130 b Fc(n)o(um)o(b)q(er)15
+b(of)e(c)o(haracters)g(b)q(efore)h(line)g(folded)910 449 y
+Ff(write)e Fe(on/o\013)79 b Fc(Allo)o(w)13 b(or)h(forbid)g(patc)o(hing)h
+(binary)m(,)g(core)e(\014les)1206 486 y(\(when)g(reop)q(ened)h(with)g
+Ff(exec)f Fc(or)g Ff(core)p Fc(\))910 526 y Ff(history)f Fb(:)7
+b(:)g(:)910 563 y Ff(h)14 b Fb(:)7 b(:)g(:)1185 526 y Fc(groups)14
+b(with)g(the)g(follo)o(wing)g(options:)910 598 y Ff(h)g(exp)f
+Fe(o\013/on)82 b Fc(disable/enable)14 b Ff(readline)d Fc(history)k(expansion)
+910 635 y Ff(h)f(file)e Fe(\014lename)33 b Fc(\014le)14 b(for)f(recording)h
+(GDB)f(command)h(history)910 672 y Ff(h)g(size)e Fe(size)104
+b Fc(n)o(um)o(b)q(er)15 b(of)e(commands)h(k)o(ept)h(in)f(history)h(list)910
+710 y Ff(h)f(save)e Fe(o\013/on)65 b Fc(con)o(trol)13 b(use)h(of)g(external)g
+(\014le)g(for)f(command)1206 747 y(history)910 803 y Ff(print)f
+Fb(:)7 b(:)g(:)910 840 y Ff(p)14 b Fb(:)7 b(:)g(:)1185 803
+y Fc(groups)14 b(with)g(the)g(follo)o(wing)g(options:)910 882
+y Ff(p)g(address)d Fe(on/o\013)h Fc(prin)o(t)j(memory)f(addresses)g(in)g
+(stac)o(ks,)h(v)n(alues)910 923 y Ff(p)f(array)e Fe(o\013/on)47
+b Fc(compact)13 b(or)g(attractiv)o(e)g(format)h(for)g(arra)o(ys)910
+965 y Ff(p)g(demangl)d Fe(on/o\013)h Fc(source)h(\(demangled\))h(or)g(in)o
+(ternal)g(form)g(for)1206 1002 y(C++)g(sym)o(b)q(ols)910 1042
+y Ff(p)g(asm-dem)d Fe(on/o\013)h Fc(demangle)i(C++)g(sym)o(b)q(ols)h(in)g
+(mac)o(hine-)1206 1079 y(instruction)g(output)910 1118 y Ff(p)f(elements)d
+Fe(limit)17 b Fc(n)o(um)o(b)q(er)e(of)e(arra)o(y)h(elemen)o(ts)g(to)g(displa)
+o(y)910 1160 y Ff(p)g(object)e Fe(on/o\013)29 b Fc(prin)o(t)15
+b(C++)f(deriv)o(ed)h(t)o(yp)q(es)g(for)e(ob)r(jects)910 1201
+y Ff(p)h(pretty)e Fe(o\013/on)29 b Fc(struct)14 b(displa)o(y:)23
+b(compact)13 b(or)g(inden)o(ted)910 1243 y Ff(p)h(union)e Fe(on/o\013)47
+b Fc(displa)o(y)15 b(of)f(union)h(mem)o(b)q(ers)910 1284 y
+Ff(p)f(vtbl)e Fe(o\013/on)65 b Fc(displa)o(y)15 b(of)f(C++)h(virtual)f
+(function)h(tables)875 1359 y Ff(show)e(commands)81 b Fc(sho)o(w)13
+b(last)h(10)f(commands)875 1396 y Ff(show)g(commands)e Fe(n)51
+b Fc(sho)o(w)13 b(10)g(commands)h(around)g(n)o(um)o(b)q(er)h
+Fe(n)875 1434 y Ff(show)e(commands)e(+)52 b Fc(sho)o(w)13 b(next)i(10)e
+(commands)875 1521 y Fg(W)l(orking)g(Files)875 1573 y Ff(file)g
+Fd([)p Fe(\014le)p Fd(])156 b Fc(use)14 b Fe(\014le)f Fc(for)h(b)q(oth)g(sym)
+o(b)q(ols)h(and)f(executable;)1206 1610 y(with)g(no)g(arg,)f(discard)h(b)q
+(oth)875 1659 y Ff(core)f Fd([)p Fe(\014le)p Fd(])156 b Fc(read)13
+b Fe(\014le)h Fc(as)f(coredump;)i(or)e(discard)875 1713 y Ff(exec)g
+Fd([)p Fe(\014le)p Fd(])156 b Fc(use)14 b Fe(\014le)f Fc(as)h(executable)g
+(only;)h(or)e(discard)875 1767 y Ff(symbol)f Fd([)p Fe(\014le)p
+Fd(])121 b Fc(use)14 b(sym)o(b)q(ol)h(table)f(from)g Fe(\014le)p
+Fc(;)f(or)h(discard)875 1810 y Ff(load)f Fe(\014le)180 b Fc(dynamically)15
+b(link)h Fe(\014le)f Fc(and)f(add)g(its)h(sym)o(b)q(ols)875
+1848 y Ff(add-sym)c Fe(\014le)j(addr)45 b Fc(read)13 b(additional)i(sym)o(b)q
+(ols)g(from)f Fe(\014le)p Fc(,)1206 1885 y(dynamically)h(loaded)f(at)f
+Fe(addr)875 1923 y Ff(info)g(files)135 b Fc(displa)o(y)15 b(w)o(orking)f
+(\014les)g(and)g(targets)f(in)i(use)875 1961 y Ff(path)e Fe(dirs)167
+b Fc(add)14 b Fe(dirs)f Fc(to)g(fron)o(t)h(of)g(path)g(searc)o(hed)f(for)1206
+1998 y(executable)g(and)h(sym)o(b)q(ol)h(\014les)875 2037 y
+Ff(show)e(path)153 b Fc(displa)o(y)15 b(executable)f(and)g(sym)o(b)q(ol)h
+(\014le)f(path)875 2074 y Ff(info)f(share)135 b Fc(list)15
+b(names)e(of)h(shared)g(libraries)h(curren)o(tly)1206 2111
+y(loaded)p 1900 -217 V 1900 2175 V 1975 -183 a Fg(Source)e(Files)1975
+-138 y Ff(dir)g Fe(names)148 b Fc(add)14 b(directory)g Fe(names)f
+Fc(to)h(fron)o(t)g(of)f(source)2306 -100 y(path)1975 -62 y
+Ff(dir)256 b Fc(clear)13 b(source)h(path)1975 -25 y Ff(show)f(dir)171
+b Fc(sho)o(w)14 b(curren)o(t)g(source)f(path)1975 50 y Ff(list)238
+b Fc(sho)o(w)14 b(next)g(ten)g(lines)h(of)e(source)1975 87
+y Ff(list)g(-)207 b Fc(sho)o(w)14 b(previous)g(ten)g(lines)1975
+125 y Ff(list)f Fe(lines)156 b Fc(displa)o(y)15 b(source)f(surrounding)h
+Fe(lines)p Fc(,)f(sp)q(eci\014ed)2306 162 y(as:)2011 206 y
+Fd([)p Fe(\014le)p Ff(:)p Fd(])p Fe(num)122 b Fc(line)15 b(n)o(um)o(b)q(er)g
+Fd([)p Fc(in)f(named)g(\014le)p Fd(])2011 260 y([)p Fe(\014le)p
+Ff(:)p Fd(])p Fe(function)63 b Fc(b)q(eginning)15 b(of)e(function)i
+Fd([)p Fc(in)f(named)g(\014le)p Fd(])2011 303 y Ff(+)p Fe(o\013)217
+b(o\013)14 b Fc(lines)h(after)e(last)h(prin)o(ted)2011 340
+y Ff(-)p Fe(o\013)217 b(o\013)14 b Fc(lines)h(previous)f(to)g(last)g(prin)o
+(ted)2011 377 y Ff(*)p Fe(addr)n(ess)145 b Fc(line)15 b(con)o(taining)f
+Fe(addr)n(ess)1975 415 y Ff(list)f Fe(f)p Ff(,)p Fe(l)187 b
+Fc(from)14 b(line)h Fe(f)e Fc(to)g(line)i Fe(l)1975 452 y Ff(info)e(line)f
+Fe(num)76 b Fc(sho)o(w)14 b(starting,)g(ending)g(addresses)g(of)2306
+489 y(compiled)g(co)q(de)f(for)h(source)f(line)i Fe(num)1975
+528 y Ff(info)e(source)117 b Fc(sho)o(w)14 b(name)f(of)h(curren)o(t)g(source)
+f(\014le)1975 565 y Ff(info)g(sources)99 b Fc(list)15 b(all)f(source)f
+(\014les)h(in)h(use)1975 603 y Ff(forw)e Fe(r)n(e)n(gex)150
+b Fc(searc)o(h)13 b(follo)o(wing)h(source)g(lines)h(for)e Fe(r)n(e)n(gex)1975
+640 y Ff(rev)g Fe(r)n(e)n(gex)168 b Fc(searc)o(h)13 b(preceding)h(source)g
+(lines)h(for)e Fe(r)n(e)n(gex)1975 737 y Fg(GDB)g(under)f(GNU)i(Emacs)1975
+782 y Ff(M-x)f(gdb)189 b Fc(run)14 b(GDB)g(under)h(Emacs)1975
+820 y Ff(C-h)e(m)225 b Fc(describ)q(e)14 b(GDB)g(mo)q(de)1975
+857 y Ff(M-s)256 b Fc(step)14 b(one)f(line)i(\()p Ff(step)p
+Fc(\))1975 899 y Ff(M-n)256 b Fc(next)14 b(line)h(\()p Ff(next)p
+Fc(\))1975 936 y Ff(M-i)256 b Fc(step)14 b(one)f(instruction)i(\()p
+Ff(stepi)p Fc(\))1975 978 y Ff(C-c)e(C-f)189 b Fc(\014nish)15
+b(curren)o(t)f(stac)o(k)g(frame)f(\()p Ff(finish)p Fc(\))1975
+1015 y Ff(M-c)256 b Fc(con)o(tin)o(ue)14 b(\()p Ff(cont)p Fc(\))1975
+1052 y Ff(M-u)256 b Fc(up)14 b Fe(ar)n(g)f Fc(frames)h(\()p
+Ff(up)p Fc(\))1975 1094 y Ff(M-d)256 b Fc(do)o(wn)14 b Fe(ar)n(g)f
+Fc(frames)h(\()p Ff(down)p Fc(\))1975 1131 y Ff(C-x)f(&)225
+b Fc(cop)o(y)14 b(n)o(um)o(b)q(er)h(from)f(p)q(oin)o(t,)h(insert)f(at)f(end)
+1975 1169 y Ff(C-x)g(SPC)189 b Fc(\(in)14 b(source)g(\014le\))g(set)f(break)h
+(at)g(p)q(oin)o(t)1975 1267 y Fg(GDB)f(License)1975 1313 y
+Ff(show)g(copying)99 b Fc(Displa)o(y)15 b(GNU)e(General)g(Public)i(License)
+1975 1350 y Ff(show)e(warranty)81 b Fc(There)13 b(is)i(NO)e(W)l(ARRANTY)g
+(for)h(GDB.)2306 1387 y(Displa)o(y)h(full)g(no-w)o(arran)o(t)o(y)f(statemen)o
+(t.)2024 1622 y Fh(Cop)o(yrigh)o(t)2185 1621 y(c)2171 1622
+y Fa(\015)o Fh(1991,)h(1992,)f(1993)h(F)n(ree)d(Soft)o(w)o(are)i(F)n
+(oundation,)f(Inc.)2215 1660 y(Roland)i(P)o(esc)o(h)f(\(p)q(esc)o(h@cygn)o
+(us.com\))1997 1697 y(The)f(author)h(assumes)f(no)h(resp)q(onsibilit)o(y)j
+(for)c(an)o(y)h(errors)g(on)g(this)h(card.)1975 1759 y(This)g(card)e(ma)o(y)g
+(b)q(e)g(freely)h(distributed)g(under)f(the)g(terms)g(of)g(the)h(GNU)1975
+1797 y(General)h(Public)g(License.)2012 1834 y(Please)f(con)o(tribute)g(to)g
+(dev)o(elopmen)o(t)e(of)i(this)h(card)e(b)o(y)h(annotating)h(it.)1975
+1896 y(GDB)g(itself)f(is)h(free)e(soft)o(w)o(are;)g(y)o(ou)h(are)g(w)o
+(elcome)e(to)i(distribute)h(copies)f(of)1975 1934 y(it)h(under)e(the)g(terms)
+g(of)g(the)g(GNU)i(General)g(Public)g(License.)20 b(There)12
+b(is)1975 1971 y(absolutely)k(no)d(w)o(arran)o(t)o(y)i(for)e(GDB.)p
+eop
+%%Trailer
+end
+userdict /end-hook known{end-hook}if
+%%EOF
diff --git a/gnu/usr.bin/gdb/doc/refcard.tex b/gnu/usr.bin/gdb/doc/refcard.tex
new file mode 100644
index 000000000000..dfad02e6bb04
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/refcard.tex
@@ -0,0 +1,646 @@
+%%%%%%%%%%%%%%%% gdb-refcard.tex %%%%%%%%%%%%%%%%
+
+%This file is TeX source for a reference card describing GDB, the GNU debugger.
+%$Id: refcard.tex,v 1.1 1994/06/10 13:34:43 paul Exp $
+%Copyright (C) 1991, 1992 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
+% 1937 Landings Drive
+% Mountain View, CA 94043 USA
+%
+% +1 415 903 1400
+%
+%
+%
+% 22-AUG-1993 Andreas Vogel
+%
+% Modifications made in order to handle different papersizes correctly.
+% You only have to set the total width and height of the paper, the
+% horizontal and vertical margin space measured from *paper edge*
+% and the interline and interspec spacing.
+% In order to support a new papersize, you have to fiddle with the
+% latter four dimensions. Just try out a few values.
+% All other values will be computed at process time so it should be
+% quite easy to support different paper sizes - only four values to
+% guess :-)
+%
+% To find the configuration places, just search for the string
+% "CONFIGURATION".
+%
+% Andreas Vogel (av@ssw.de)
+%
+%
+%
+% Uncomment the following `magnification' command if you want to print
+% out in a larger font. Caution! You may need larger paper. You had
+% best avoid using 3-column output if you try this. See the ``Three
+% column format'' section below if you want to print in three column
+% format.
+%
+%\magnification=\magstep 1
+%
+% NOTE ON INTENTIONAL OMISSIONS: This reference card includes most GDB
+% commands, but due to space constraints there are some things I chose
+% to omit. In general, not all synonyms for commands are covered, nor
+% all variations of a command.
+% The GDB-under-Emacs section omits gdb-mode functions without default
+% keybindings. GDB startup options are not described.
+% set print sevenbit-strings, set symbol-reloading omitted.
+% printsyms, printpsyms, omitted since they're for GDB maintenance primarily
+% share omitted due to obsolescence
+% set check range/type omitted at least til code is in GDB.
+%
+%-------------------- Three column format -----------------------
+
+%%%% --- To disable three column format, comment out this entire section
+
+% Three-column format for landscape printing
+
+%-------- Papersize defs:
+
+\newdimen\totalwidth \newdimen\totalheight
+\newdimen\hmargin \newdimen\vmargin
+\newdimen\secskip \newdimen\lskip
+\newdimen\barwidth \newdimen\barheight
+\newdimen\intersecwidth
+
+%%
+%% START CONFIGURATION - PAPERSIZE DEFINITIONS
+%------- Papersize params:
+%% US letter paper (8.5x11in)
+%%
+\totalwidth=11in % total width of paper
+\totalheight=8.5in % total height of paper
+\hmargin=.25in % horizontal margin width
+\vmargin=.25in % vertical margin width
+\secskip=1pc % space between refcard secs
+\lskip=2pt % extra skip between \sec entries
+%------- end papersize params
+%%
+%% change according to personal taste, not papersize dependent
+%%
+\barwidth=.1pt % width of the cropmark bar
+\barheight=2pt % height of the cropmark bar
+\intersecwidth=0.5em % width between \itmwid and \dfnwid
+%%
+%% END CONFIGURATION - PAPERSIZE DEFINITIONS
+%%
+
+%%
+%% values to be computed - nothing to configure
+%%
+\newdimen\fullhsize % width of area without margins
+\newdimen\itmwid % width of item column
+\newdimen\dfnwid % width of definition column
+\newdimen\temp % only for temporary use
+
+%%
+%% adjust the offsets so the margins are measured *from paper edge*
+%%
+\hoffset=-1in \advance \hoffset by \hmargin
+\voffset=-1in \advance \voffset by \vmargin
+
+%%
+%% fullhsize = totalwidth - (2 * hmargin)
+%%
+\fullhsize=\totalwidth
+\temp=\hmargin \multiply \temp by 2 \advance \fullhsize by -\temp
+
+%%
+%% hsize = (fullhsize - (4 * hmargin) - (2 * barwidth)) / 3
+%%
+\hsize=\fullhsize
+\temp=\hmargin \multiply \temp by 4 \advance \hsize by -\temp
+\temp=\barwidth \multiply \temp by 2 \advance \hsize by -\temp
+\divide \hsize by 3
+
+%%
+%% vsize = totalheight - (2 * vmargin)
+%%
+\vsize=\totalheight
+\temp=\vmargin \multiply \temp by 2 \advance \vsize by -\temp
+
+%%
+%% itmwid = (hsize - intersecwidth) * 1/3
+%% dfnwid = (hsize - intersecwidth) * 2/3
+%%
+\temp=\hsize \advance \temp by -\intersecwidth \divide \temp by 3
+\itmwid=\temp
+\dfnwid=\hsize \advance \dfnwid by -\itmwid
+
+%-------- end papersize defs
+
+
+\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
+ }
+
+%%
+%% START CONFIGURATION - ALTERNATIVE FOLDING GUIDES
+%%
+%% For NO printed folding guide,
+%% comment out other \def\vdecor's and uncomment:
+
+%\def\vdecor{\hskip\hmargin plus1fil\hskip\barwidth plus1fil\hskip\hmargin plus1fil}
+
+%% For SOLID LINE folding guide,
+%% comment out other \def\vdecor's and uncomment:
+
+%\def\vdecor{\hskip\hmargin plus1fil \vrule width \barwidth \hskip\hmargin plus1fil}
+
+%% For SMALL MARKS NEAR TOP AND BOTTOM as folding guide,
+%% comment out other \def\vdecor's and uncomment:
+
+\def\vdecor{\hskip\hmargin plus1fil
+\vbox to \vsize{\hbox to \barwidth{\vrule height\barheight width\barwidth}\vfill
+\hbox to \barwidth{\vrule height\barheight width\barwidth}}%THIS PERCENT SIGN IS ESSENTIAL
+\hskip\hmargin plus1fil}
+
+%%
+%% END CONFIGURATION - ALTERNATIVES FOR FOLDING GUIDES
+%%
+
+\def\tripleformat{\shipout\vbox{\fulline{\box\leftcolumn\vdecor
+ \box\centercolumn\vdecor
+ \columnbox}
+ }
+ \advancepageno}
+\def\columnbox{\leftline{\pagebody}}
+\def\bye{\par\vfill
+ \supereject
+ \if R\lcr \null\vfill\eject\fi
+ \end}
+
+%-------------------- end three column format -----------------------
+
+%-------------------- Computer Modern font defs: --------------------
+\font\bbf=cmbx10
+\font\vbbf=cmbx12
+\font\smrm=cmr6
+\font\brm=cmr10
+\font\rm=cmr7
+\font\it=cmti7
+\font\tt=cmtt8
+%-------------------- end font defs ---------------------------------
+
+%
+\hyphenpenalty=5000\tolerance=2000\raggedright\raggedbottom
+\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 \secskip
+\halign{%
+%COL 1 (of halign):
+\vtop{\hsize=\itmwid\tt
+##\par\vskip \lskip }\hfil
+%COL 2 (of halign):
+&\vtop{\hsize=\dfnwid\hangafter=1\hangindent=\intersecwidth
+\rm ##\par\vskip \lskip}\cr
+%Tail of \long\def fills in halign body with \sec args:
+\noalign{{\bbf #1}\vskip \lskip}
+#2
+}
+}
+
+{\vbbf GDB QUICK REFERENCE}\hfil{\smrm GDB Version 4}\qquad
+
+\sec Essential Commands;
+gdb {\it program} \opt{{\it core}}&debug {\it program} \opt{using
+coredump {\it core}}\cr
+b \opt{\it file\tt:}{\it function}&set breakpoint at {\it function} \opt{in \it file}\cr
+run \opt{{\it arglist}}&start your program \opt{with {\it arglist}}\cr
+bt& backtrace: display program stack\cr
+p {\it expr}&display the value of an expression\cr
+c &continue running your program\cr
+n &next line, stepping over function calls\cr
+s &next line, stepping into function calls\cr
+\endsec
+
+\sec Starting GDB;
+gdb&start 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
+gdb --help&describe command line options\cr
+\endsec
+
+\sec Stopping GDB;
+quit&exit GDB; also {\tt q} or {\tt EOF} (eg \ctl{d})\cr
+INTERRUPT&(eg \ctl{c}) terminate current command, or send to running process\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 your program with input, output
+redirected\cr
+\cr
+kill&kill running program\cr
+\cr
+tty {\it dev}&use {\it dev} as stdin and stdout 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 string}&set environment variable {\it var}\cr
+unset 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
+\line{\smrm \opt{ } surround optional arguments \hfill $\ldots$ show
+one or more arguments}
+\vskip\baselineskip
+\centerline{\smrm \copyright 1991, 1992 Free Software Foundation, Inc.\qquad Permissions on back}
+\eject
+\sec Breakpoints and Watchpoints;
+break \opt{\it file\tt:}{\it line}\par
+b \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 func}&set breakpoint at {\it
+func} \opt{in \it file}\cr
+break +{\it offset}\par
+break -{\it offset}&set break at {\it offset} lines 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 n} \opt{\it expr}&new conditional expression on breakpoint
+{\it n}; 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}&break 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 n}}&delete breakpoints
+\opt{or breakpoint {\it n}}\cr
+\cr
+disable \opt{{\it n}}&disable breakpoints
+\opt{or breakpoint {\it n}}
+\cr
+enable \opt{{\it n}}&enable breakpoints
+\opt{or breakpoint {\it n}}
+\cr
+enable once \opt{{\it n}}&enable breakpoints \opt{or breakpoint {\it n}};
+disable again when reached
+\cr
+enable del \opt{{\it n}}&enable breakpoints \opt{or breakpoint {\it n}};
+delete when reached
+\cr
+\cr
+ignore {\it n} {\it count}&ignore breakpoint {\it n}, {\it count}
+times\cr
+\cr
+commands {\it n}\par
+\qquad \opt{\tt silent}\par
+\qquad {\it command-list}&execute GDB {\it command-list} every time breakpoint {\it n} is reached. \opt{{\tt silent} suppresses default
+display}\cr
+end&end of {\it command-list}\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}&describe selected frame, or frame at
+{\it addr}\cr
+info args&arguments of selected frame\cr
+info locals&local variables of selected frame\cr
+info reg \opt{\it rn}$\ldots$\par
+info all-reg \opt{\it rn}&register values \opt{for regs {\it rn\/}} in
+selected frame; {\tt all-reg} includes floating point\cr
+info catch&exception handlers active in selected frame\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
+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
+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})\cr
+finish&run until selected stack frame returns\cr
+return \opt{\it expr}&pop selected stack frame without executing
+\opt{setting return value}\cr
+signal {\it num}&resume execution with signal {\it s} (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 Display;
+print \opt{\tt/{\it f}\/} \opt{\it expr}\par
+p \opt{\tt/{\it f}\/} \opt{\it expr}&show value of {\it expr} \opt{or
+last value \tt \$} according to format {\it f}:\cr
+\qquad x&hexadecimal\cr
+\qquad d&signed decimal\cr
+\qquad u&unsigned decimal\cr
+\qquad o&octal\cr
+\qquad t&binary\cr
+\qquad a&address, absolute and relative\cr
+\qquad c&character\cr
+\qquad f&floating point\cr
+call \opt{\tt /{\it f}\/} {\it expr}&like {\tt print} but does not display
+{\tt void}\cr
+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 memory as machine instructions\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 n}&remove number(s) {\it n} from list of
+automatically displayed expressions\cr
+disable disp {\it n}&disable display for expression(s) number {\it
+n}\cr
+enable disp {\it n}&enable display for expression(s) number {\it
+n}\cr
+info display&numbered list of display expressions\cr
+\endsec
+
+\vfill\eject
+
+\sec Expressions;
+{\it expr}&an expression in C, C++, or Modula-2 (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
+\$&most recent displayed value\cr
+\${\it n}&{\it n}th displayed value\cr
+\$\$&displayed value previous to \$\cr
+\$\${\it n}&{\it n}th displayed value back from \$\cr
+\$\_&last address examined with {\tt x}\cr
+\$\_\_&value at address \$\_\cr
+\${\it var}&convenience variable; assign any value\cr
+\cr
+show values \opt{{\it n}}&show last 10 values \opt{or surrounding
+\${\it n}}\cr
+show convenience&display all convenience variables\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
+whatis \opt{\it expr}\par
+ptype \opt{\it expr}&show data type of {\it expr} \opt{or \tt \$}
+without evaluating; {\tt ptype} gives more detail\cr
+ptype {\it type}&describe type, struct, union, or enum\cr
+\endsec
+
+\sec GDB Scripts;
+source {\it script}&read, execute GDB commands from file {\it
+script}\cr
+\cr
+define {\it cmd}\par
+\qquad {\it command-list}&create new GDB command {\it cmd};
+execute script defined by {\it command-list}\cr
+end&end of {\it command-list}\cr
+document {\it cmd}\par
+\qquad {\it help-text}&create online documentation
+for new GDB command {\it cmd}\cr
+end&end of {\it help-text}\cr
+\endsec
+
+\sec Signals;
+handle {\it signal} {\it act}&specify GDB actions for {\it signal}:\cr
+\quad print&announce signal\cr
+\quad noprint&be silent for signal\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 signals&show table of signals, GDB action for each\cr
+\endsec
+
+\sec Debugging Targets;
+target {\it type} {\it param}&connect to target machine, process, or file\cr
+help target&display available targets\cr
+attach {\it param}&connect to another process\cr
+detach&release target from GDB control\cr
+\endsec
+
+\vfill\eject
+\sec Controlling GDB;
+set {\it param} {\it value}&set one of GDB's internal parameters\cr
+show {\it param}&display current setting of parameter\cr
+\xtra{\rm Parameters understood by {\tt set} and {\tt show}:}
+\quad complaints {\it limit}&number of messages on unusual symbols\cr
+\quad confirm {\it on/off}&enable or disable cautionary queries\cr
+\quad editing {\it on/off}&control {\tt readline} command-line editing\cr
+\quad height {\it lpp}&number of lines before pause in display\cr
+\quad language {\it lang}&Language for GDB expressions ({\tt auto}, {\tt c} or
+{\tt modula-2})\cr
+\quad listsize {\it n}&number of lines shown by {\tt list}\cr
+\quad prompt {\it str}&use {\it str} as GDB prompt\cr
+\quad radix {\it base}&octal, decimal, or hex number representation\cr
+\quad verbose {\it on/off}&control messages when loading
+symbols\cr
+\quad width {\it cpl}&number of characters before line folded\cr
+\quad write {\it on/off}&Allow or forbid patching binary, core files
+(when reopened with {\tt exec} or {\tt core})
+\cr
+\quad history $\ldots$\par
+\quad h $\ldots$&groups with the following options:\cr
+\quad h exp {\it off/on}&disable/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 save {\it off/on}&control use of external file for
+command history\cr
+\cr
+\quad print $\ldots$\par
+\quad p $\ldots$&groups with the following options:\cr
+\quad p address {\it on/off}&print memory addresses in stacks,
+values\cr
+\quad p array {\it off/on}&compact or attractive format for
+arrays\cr
+\quad p demangl {\it on/off}&source (demangled) or internal form for C++
+symbols\cr
+\quad p asm-dem {\it on/off}&demangle C++ symbols in
+machine-instruction output\cr
+\quad p elements {\it limit}&number of array elements to display\cr
+\quad p object {\it on/off}&print C++ derived types for objects\cr
+\quad p pretty {\it off/on}&struct display: compact or indented\cr
+\quad p union {\it on/off}&display of union members\cr
+\quad p vtbl {\it off/on}&display of C++ virtual function
+tables\cr
+\cr
+show commands&show last 10 commands\cr
+show commands {\it n}&show 10 commands around number {\it n}\cr
+show commands +&show next 10 commands\cr
+\endsec
+
+\sec Working Files;
+file \opt{\it file}&use {\it file} for both symbols and executable;
+with no arg, discard both\cr
+core \opt{\it file}&read {\it file} as coredump; or discard\cr
+exec \opt{\it file}&use {\it file} as executable only; or discard\cr
+symbol \opt{\it file}&use symbol table from {\it file}; or discard\cr
+load {\it file}&dynamically link {\it file\/} and add its symbols\cr
+add-sym {\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
+path {\it dirs}&add {\it dirs} to front of path searched for
+executable and symbol files\cr
+show path&display executable and symbol file path\cr
+info share&list names of shared libraries currently loaded\cr
+\endsec
+
+\vfill\eject
+\sec Source Files;
+dir {\it names}&add directory {\it names} to front of source path\cr
+dir&clear source path\cr
+show 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 surrounding {\it lines},
+specified as:\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
+info source&show name of current source file\cr
+info sources&list all source files in use\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} \&&copy number from point, insert at end\cr
+\ctl{x} SPC&(in source file) set break at point\cr
+\endsec
+
+\sec GDB License;
+show copying&Display GNU General Public License\cr
+show warranty&There is NO WARRANTY for GDB. Display full no-warranty
+statement.\cr
+\endsec
+
+
+\vfill
+{\smrm\parskip=6pt
+\centerline{Copyright \copyright 1991, 1992, 1993 Free Software Foundation, Inc.}
+\centerline{Roland Pesch (pesch@cygnus.com)}
+\centerline{The author assumes no responsibility for any errors on this card.}
+
+This card may be freely distributed under the terms of the GNU
+General Public License.
+
+\centerline{Please contribute to development of this card by
+annotating it.}
+
+GDB itself is free software; you are welcome to distribute copies of
+it under the terms of the GNU General Public License. There is
+absolutely no warranty for GDB.
+}
+\end
diff --git a/gnu/usr.bin/gdb/doc/remote.texi b/gnu/usr.bin/gdb/doc/remote.texi
new file mode 100644
index 000000000000..5b7ec90e1e8b
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/remote.texi
@@ -0,0 +1,1294 @@
+@c -*- Texinfo -*-
+@c Copyright (c) 1990 1991 1992 1993 Free Software Foundation, Inc.
+@c This file is part of the source for the GDB manual.
+@c This text diverted to "Remote Debugging" section in general case;
+@c however, if we're doing a manual specifically for one of these, it
+@c belongs up front (in "Getting In and Out" chapter).
+
+@ifset REMOTESTUB
+@node Remote Serial
+@subsection The @value{GDBN} remote serial protocol
+
+@cindex remote serial debugging, overview
+To debug a program running on another machine (the debugging
+@dfn{target} machine), you must first arrange for all the usual
+prerequisites for the program to run by itself. For example, for a C
+program, you need
+
+@enumerate
+@item
+A startup routine to set up the C runtime environment; these usually
+have a name like @file{crt0}. The startup routine may be supplied by
+your hardware supplier, or you may have to write your own.
+
+@item
+You probably need a C subroutine library to support your program's
+subroutine calls, notably managing input and output.
+
+@item
+A way of getting your program to the other machine---for example, a
+download program. These are often supplied by the hardware
+manufacturer, but you may have to write your own from hardware
+documentation.
+@end enumerate
+
+The next step is to arrange for your program to use a serial port to
+communicate with the machine where @value{GDBN} is running (the @dfn{host}
+machine). In general terms, the scheme looks like this:
+
+@table @emph
+@item On the host,
+@value{GDBN} already understands how to use this protocol; when everything
+else is set up, you can simply use the @samp{target remote} command
+(@pxref{Targets,,Specifying a Debugging Target}).
+
+@item On the target,
+you must link with your program a few special-purpose subroutines that
+implement the @value{GDBN} remote serial protocol. The file containing these
+subroutines is called a @dfn{debugging stub}.
+
+@ifset GDBSERVER
+On certain remote targets, you can use an auxiliary program
+@code{gdbserver} instead of linking a stub into your program.
+@xref{Server,,Using the @code{gdbserver} program}, for details.
+@end ifset
+@end table
+
+The debugging stub is specific to the architecture of the remote
+machine; for example, use @file{sparc-stub.c} to debug programs on
+@sc{sparc} boards.
+
+@cindex remote serial stub list
+These working remote stubs are distributed with @value{GDBN}:
+
+@table @code
+@item sparc-stub.c
+@kindex sparc-stub.c
+For @sc{sparc} architectures.
+
+@item m68k-stub.c
+@kindex m68k-stub.c
+@cindex Motorola 680x0
+@cindex 680x0
+For Motorola 680x0 architectures.
+
+@item i386-stub.c
+@kindex i386-stub.c
+@cindex Intel
+@cindex 386
+For Intel 386 and compatible architectures.
+@end table
+
+The @file{README} file in the @value{GDBN} distribution may list other
+recently added stubs.
+
+@menu
+* Stub Contents:: What the stub can do for you
+* Bootstrapping:: What you must do for the stub
+* Debug Session:: Putting it all together
+* Protocol:: Outline of the communication protocol
+@ifset GDBSERVER
+* Server:: Using the `gdbserver' program
+@end ifset
+@end menu
+
+@node Stub Contents
+@subsubsection What the stub can do for you
+
+@cindex remote serial stub
+The debugging stub for your architecture supplies these three
+subroutines:
+
+@table @code
+@item set_debug_traps
+@kindex set_debug_traps
+@cindex remote serial stub, initialization
+This routine arranges for @code{handle_exception} to run when your
+program stops. You must call this subroutine explicitly near the
+beginning of your program.
+
+@item handle_exception
+@kindex handle_exception
+@cindex remote serial stub, main routine
+This is the central workhorse, but your program never calls it
+explicitly---the setup code arranges for @code{handle_exception} to
+run when a trap is triggered.
+
+@code{handle_exception} takes control when your program stops during
+execution (for example, on a breakpoint), and mediates communications
+with @value{GDBN} on the host machine. This is where the communications
+protocol is implemented; @code{handle_exception} acts as the @value{GDBN}
+representative on the target machine; it begins by sending summary
+information on the state of your program, then continues to execute,
+retrieving and transmitting any information @value{GDBN} needs, until you
+execute a @value{GDBN} command that makes your program resume; at that point,
+@code{handle_exception} returns control to your own code on the target
+machine.
+
+@item breakpoint
+@cindex @code{breakpoint} subroutine, remote
+Use this auxiliary subroutine to make your program contain a
+breakpoint. Depending on the particular situation, this may be the only
+way for @value{GDBN} to get control. For instance, if your target
+machine has some sort of interrupt button, you won't need to call this;
+pressing the interrupt button will transfer control to
+@code{handle_exception}---in effect, to @value{GDBN}. On some machines,
+simply receiving characters on the serial port may also trigger a trap;
+again, in that situation, you don't need to call @code{breakpoint} from
+your own program---simply running @samp{target remote} from the host
+@value{GDBN} session will get control.
+
+Call @code{breakpoint} if none of these is true, or if you simply want
+to make certain your program stops at a predetermined point for the
+start of your debugging session.
+@end table
+
+@node Bootstrapping
+@subsubsection What you must do for the stub
+
+@cindex remote stub, support routines
+The debugging stubs that come with @value{GDBN} are set up for a particular
+chip architecture, but they have no information about the rest of your
+debugging target machine. To allow the stub to work, you must supply
+these special low-level subroutines:
+
+@table @code
+@item int getDebugChar()
+@kindex getDebugChar
+Write this subroutine to read a single character from the serial port.
+It may be identical to @code{getchar} for your target system; a
+different name is used to allow you to distinguish the two if you wish.
+
+@item void putDebugChar(int)
+@kindex putDebugChar
+Write this subroutine to write a single character to the serial port.
+It may be identical to @code{putchar} for your target system; a
+different name is used to allow you to distinguish the two if you wish.
+
+@item void exceptionHandler (int @var{exception_number}, void *@var{exception_address})
+@kindex exceptionHandler
+Write this function to install @var{exception_address} in the exception
+handling tables. You need to do this because the stub does not have any
+way of knowing what the exception handling tables on your target system
+are like (for example, the processor's table might be in @sc{rom},
+containing entries which point to a table in @sc{ram}).
+@var{exception_number} is the exception number which should be changed;
+its meaning is architecture-dependent (for example, different numbers
+might represent divide by zero, misaligned access, etc). When this
+exception occurs, control should be transferred directly to
+@var{exception_address}, and the processor state (stack, registers,
+etc.) should be just as it is when a processor exception occurs. So if
+you want to use a jump instruction to reach @var{exception_address}, it
+should be a simple jump, not a jump to subroutine.
+
+For the 386, @var{exception_address} should be installed as an interrupt
+gate so that interrupts are masked while the handler runs. The gate
+should be at privilege level 0 (the most privileged level). The
+@sc{sparc} and 68k stubs are able to mask interrupts themself without
+help from @code{exceptionHandler}.
+
+@item void flush_i_cache()
+@kindex flush_i_cache
+Write this subroutine to flush the instruction cache, if any, on your
+target machine. If there is no instruction cache, this subroutine may
+be a no-op.
+
+On target machines that have instruction caches, @value{GDBN} requires this
+function to make certain that the state of your program is stable.
+@end table
+
+@noindent
+You must also make sure this library routine is available:
+
+@table @code
+@item void *memset(void *, int, int)
+@kindex memset
+This is the standard library function @code{memset} that sets an area of
+memory to a known value. If you have one of the free versions of
+@code{libc.a}, @code{memset} can be found there; otherwise, you must
+either obtain it from your hardware manufacturer, or write your own.
+@end table
+
+If you do not use the GNU C compiler, you may need other standard
+library subroutines as well; this will vary from one stub to another,
+but in general the stubs are likely to use any of the common library
+subroutines which @code{gcc} generates as inline code.
+
+
+@node Debug Session
+@subsubsection Putting it all together
+
+@cindex remote serial debugging summary
+In summary, when your program is ready to debug, you must follow these
+steps.
+
+@enumerate
+@item
+Make sure you have the supporting low-level routines
+(@pxref{Bootstrapping,,What you must do for the stub}):
+@display
+@code{getDebugChar}, @code{putDebugChar},
+@code{flush_i_cache}, @code{memset}, @code{exceptionHandler}.
+@end display
+
+@item
+Insert these lines near the top of your program:
+
+@example
+set_debug_traps();
+breakpoint();
+@end example
+
+@item
+For the 680x0 stub only, you need to provide a variable called
+@code{exceptionHook}. Normally you just use
+
+@example
+void (*exceptionHook)() = 0;
+@end example
+
+but if before calling @code{set_debug_traps}, you set it to point to a
+function in your program, that function is called when
+@code{@value{GDBN}} continues after stopping on a trap (for example, bus
+error). The function indicated by @code{exceptionHook} is called with
+one parameter: an @code{int} which is the exception number.
+
+@item
+Compile and link together: your program, the @value{GDBN} debugging stub for
+your target architecture, and the supporting subroutines.
+
+@item
+Make sure you have a serial connection between your target machine and
+the @value{GDBN} host, and identify the serial port used for this on the host.
+
+@item
+@c The "remote" target now provides a `load' command, so we should
+@c document that. FIXME.
+Download your program to your target machine (or get it there by
+whatever means the manufacturer provides), and start it.
+
+@item
+To start remote debugging, run @value{GDBN} on the host machine, and specify
+as an executable file the program that is running in the remote machine.
+This tells @value{GDBN} how to find your program's symbols and the contents
+of its pure text.
+
+@cindex serial line, @code{target remote}
+Then establish communication using the @code{target remote} command.
+Its argument specifies how to communicate with the target
+machine---either via a devicename attached to a direct serial line, or a
+TCP port (usually to a terminal server which in turn has a serial line
+to the target). For example, to use a serial line connected to the
+device named @file{/dev/ttyb}:
+
+@example
+target remote /dev/ttyb
+@end example
+
+@cindex TCP port, @code{target remote}
+To use a TCP connection, use an argument of the form
+@code{@var{host}:port}. For example, to connect to port 2828 on a
+terminal server named @code{manyfarms}:
+
+@example
+target remote manyfarms:2828
+@end example
+@end enumerate
+
+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 @code{detach}
+command.
+
+@cindex interrupting remote programs
+@cindex remote programs, interrupting
+Whenever @value{GDBN} is waiting for the remote program, if you type the
+interrupt character (often @key{C-C}), @value{GDBN} attempts to stop the
+program. This may or may not succeed, depending in part on the hardware
+and the serial drivers the remote system uses. If you type the
+interrupt character once again, @value{GDBN} displays this prompt:
+
+@example
+Interrupted while waiting for the program.
+Give up (and stop debugging it)? (y or n)
+@end example
+
+If you type @kbd{y}, @value{GDBN} abandons the remote debugging session.
+(If you decide you want to try again later, you can use @samp{target
+remote} again to connect once more.) If you type @kbd{n}, @value{GDBN}
+goes back to waiting.
+
+@node Protocol
+@subsubsection Outline of the communication protocol
+
+@cindex debugging stub, example
+@cindex remote stub, example
+@cindex stub example, remote debugging
+The stub files provided with @value{GDBN} implement the target side of the
+communication protocol, and the @value{GDBN} side is implemented in the
+@value{GDBN} source file @file{remote.c}. Normally, you can simply allow
+these subroutines to communicate, and ignore the details. (If you're
+implementing your own stub file, you can still ignore the details: start
+with one of the existing stub files. @file{sparc-stub.c} is the best
+organized, and therefore the easiest to read.)
+
+However, there may be occasions when you need to know something about
+the protocol---for example, if there is only one serial port to your
+target machine, you might want your program to do something special if
+it recognizes a packet meant for @value{GDBN}.
+
+@cindex protocol, @value{GDBN} remote serial
+@cindex serial protocol, @value{GDBN} remote
+@cindex remote serial protocol
+All @value{GDBN} commands and responses (other than acknowledgements, which
+are single characters) are sent as a packet which includes a
+checksum. A packet is introduced with the character @samp{$}, and ends
+with the character @samp{#} followed by a two-digit checksum:
+
+@example
+$@var{packet info}#@var{checksum}
+@end example
+
+@cindex checksum, for @value{GDBN} remote
+@noindent
+@var{checksum} is computed as the modulo 256 sum of the @var{packet
+info} characters.
+
+When either the host or the target machine receives a packet, the first
+response expected is an acknowledgement: a single character, either
+@samp{+} (to indicate the package was received correctly) or @samp{-}
+(to request retransmission).
+
+The host (@value{GDBN}) sends commands, and the target (the debugging stub
+incorporated in your program) sends data in response. The target also
+sends data when your program stops.
+
+Command packets are distinguished by their first character, which
+identifies the kind of command.
+
+These are the commands currently supported:
+
+@table @code
+@item g
+Requests the values of CPU registers.
+
+@item G
+Sets the values of CPU registers.
+
+@item m@var{addr},@var{count}
+Read @var{count} bytes at location @var{addr}.
+
+@item M@var{addr},@var{count}:@dots{}
+Write @var{count} bytes at location @var{addr}.
+
+@item c
+@itemx c@var{addr}
+Resume execution at the current address (or at @var{addr} if supplied).
+
+@item s
+@itemx s@var{addr}
+Step the target program for one instruction, from either the current
+program counter or from @var{addr} if supplied.
+
+@item k
+Kill the target program.
+
+@item ?
+Report the most recent signal. To allow you to take advantage of the
+@value{GDBN} signal handling commands, one of the functions of the debugging
+stub is to report CPU traps as the corresponding POSIX signal values.
+@end table
+
+@kindex set remotedebug
+@kindex show remotedebug
+@cindex packets, reporting on stdout
+@cindex serial connections, debugging
+If you have trouble with the serial connection, you can use the command
+@code{set remotedebug}. This makes @value{GDBN} report on all packets sent
+back and forth across the serial line to the remote machine. The
+packet-debugging information is printed on the @value{GDBN} standard output
+stream. @code{set remotedebug off} turns it off, and @code{show
+remotedebug} will show you its current state.
+
+@ifset GDBSERVER
+@node Server
+@subsubsection Using the @code{gdbserver} program
+
+@kindex gdbserver
+@cindex remote connection without stubs
+@code{gdbserver} is a control program for Unix-like systems, which
+allows you to connect your program with a remote @value{GDBN} via
+@code{target remote}---but without linking in the usual debugging stub.
+
+@code{gdbserver} is not a complete replacement for the debugging stubs,
+because it requires essentially the same operating-system facilities
+that @value{GDBN} itself does. In fact, a system that can run
+@code{gdbserver} to connect to a remote @value{GDBN} could also run
+@var{GDBN} locally! @code{gdbserver} is sometimes useful nevertheless,
+because it is a much smaller program than @value{GDBN} itself. It is
+also easier to port than all of @var{GDBN}, so you may be able to get
+started more quickly on a new system by using @code{gdbserver}.
+
+@value{GDBN} and @code{gdbserver} communicate via either a serial line
+or a TCP connection, using the standard @value{GDBN} remote serial
+protocol.
+
+@table @emph
+@item On the target,
+you need to have a copy of the program you want to debug.
+@code{gdbserver} does not need your program's symbol table, so you can
+strip the program if necessary to save space. @value{GDBN} on the host
+system does all the symbol handling.
+
+To use the server, you must tell it how to communicate with @value{GDB};
+the name of your program; and the arguments for your program. The
+syntax is:
+
+@smallexample
+target> gdbserver @var{comm} @var{program} [ @var{args} @dots{} ]
+@end smallexample
+
+@var{comm} is either a device name (to use a serial line) or a TCP
+hostname and portnumber. For example, to debug emacs with the argument
+@samp{foo.txt} and communicate with @value{GDBN} over the serial port
+@file{/dev/com1}:
+
+@smallexample
+target> gdbserver /dev/com1 emacs foo.txt
+@end smallexample
+
+@code{gdbserver} waits passively for the host @value{GDBN} to communicate
+with it.
+
+To use a TCP connection instead of a serial line:
+
+@smallexample
+target> gdbserver host:2345 emacs foo.txt
+@end smallexample
+
+The only difference from the previous example is the first argument,
+specifying that you are communicating with the host @value{GDBN} via
+TCP. The @samp{host:2345} argument means that @code{gdbserver} is to
+expect a TCP connection from machine @samp{host} to local TCP port 2345.
+(Currently, the @samp{host} part is ignored.) You can choose any number
+you want for the port number as long as it does not conflict with any
+TCP ports already in use on the target system.@footnote{If you choose a
+port number that conflicts with another service, @code{gdbserver} prints
+an error message and exits.} You must use the same port number with the
+host @value{GDBN} @code{target remote} command.
+
+@item On the host,
+you need an unstripped copy of your program, since
+@value{GDBN} needs symbols and debugging information. Start up
+@value{GDBN} as usual, using the name of the local copy of your program
+as the first argument. (You may also need the
+@samp{--baud} option if the serial line is running at anything other than 9600 bps.)
+After that, use @code{target remote} to establish communications with @code{gdbserver}. Its argument is either
+a device name (usually a serial device, like @file{/dev/ttyb}), or a TCP
+port descriptof in the form @code{@var{host}:@var{PORT}}. For example:
+
+@smallexample
+(@value{GDBP}) target remote /dev/ttyb
+@end smallexample
+
+@noindent
+communicates with the server via serial line @file{/dev/ttyb}, and
+
+@smallexample
+(@value{GDBP}) target remote the-target:2345
+@end smallexample
+
+@noindent
+communicates via a TCP connection to port 2345 on host @file{the-target}.
+For TCP connections, you must start up @code{gdbserver} prior to using
+the @code{target remote} command. Otherwise you may get an error whose
+text depends on the host system, but which usually looks something like
+@samp{Connection refused}.
+@end table
+@end ifset
+
+@end ifset
+
+@ifset I960
+@node i960-Nindy Remote
+@subsection @value{GDBN} with a remote i960 (Nindy)
+
+@cindex Nindy
+@cindex i960
+@dfn{Nindy} is a ROM Monitor program for Intel 960 target systems. When
+@value{GDBN} is configured to control a remote Intel 960 using Nindy, you can
+tell @value{GDBN} how to connect to the 960 in several ways:
+
+@itemize @bullet
+@item
+Through command line options specifying serial port, version of the
+Nindy protocol, and communications speed;
+
+@item
+By responding to a prompt on startup;
+
+@item
+By using the @code{target} command at any point during your @value{GDBN}
+session. @xref{Target Commands, ,Commands for managing targets}.
+
+@end itemize
+
+@menu
+* Nindy Startup:: Startup with Nindy
+* Nindy Options:: Options for Nindy
+* Nindy Reset:: Nindy reset command
+@end menu
+
+@node Nindy Startup
+@subsubsection Startup with Nindy
+
+If you simply start @code{@value{GDBP}} without using any command-line
+options, you are prompted for what serial port to use, @emph{before} you
+reach the ordinary @value{GDBN} prompt:
+
+@example
+Attach /dev/ttyNN -- specify NN, or "quit" to quit:
+@end example
+
+@noindent
+Respond to the prompt with whatever suffix (after @samp{/dev/tty})
+identifies the serial port you want to use. 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 @code{target} (@pxref{Target Commands, ,Commands for managing targets}).
+
+@node Nindy Options
+@subsubsection Options for Nindy
+
+These are the startup options for beginning your @value{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 @value{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 @file{/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 @value{GDBN} should use
+the ``old'' Nindy monitor protocol to connect to the target system.
+This option is only available when @value{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 that expects the newer protocol, the connection
+fails, appearing to be a speed mismatch. @value{GDBN} repeatedly
+attempts to reconnect at several different line speeds. You can abort
+this process with an interrupt.
+@end quotation
+
+@item -brk
+Specify that @value{GDBN} should first send a @code{BREAK} signal to the target
+system, in an attempt to reset it, before connecting to a Nindy target.
+
+@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.
+
+@c @group
+@node Nindy Reset
+@subsubsection Nindy reset command
+
+@table @code
+@item reset
+@kindex reset
+For a Nindy target, 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
+@c @end group
+@end ifset
+
+@ifset AMD29K
+@node UDI29K Remote
+@subsection @value{GDBN} and the UDI protocol for AMD29K
+
+@cindex UDI
+@cindex AMD29K via UDI
+@value{GDBN} supports AMD's UDI (``Universal Debugger Interface'')
+protocol for debugging the a29k processor family. To use this
+configuration with AMD targets running the MiniMON monitor, you need the
+program @code{MONTIP}, available from AMD at no charge. You can also
+use @value{GDBN} with the UDI conformant a29k simulator program
+@code{ISSTIP}, also available from AMD.
+
+@table @code
+@item target udi @var{keyword}
+@kindex udi
+Select the UDI interface to a remote a29k board or simulator, where
+@var{keyword} is an entry in the AMD configuration file @file{udi_soc}.
+This file contains keyword entries which specify parameters used to
+connect to a29k targets. If the @file{udi_soc} file is not in your
+working directory, you must set the environment variable @samp{UDICONF}
+to its pathname.
+@end table
+
+@node EB29K Remote
+@subsection @value{GDBN} and the EBMON protocol for AMD29K
+
+@cindex EB29K board
+@cindex running 29K programs
+
+AMD distributes a 29K development board meant to fit in a PC, together
+with a DOS-hosted monitor program called @code{EBMON}. As a shorthand
+term, this development system is called the ``EB29K''. To use
+@value{GDBN} from a Unix system to run programs on the EB29K board, you
+must first connect a serial cable between the PC (which hosts the EB29K
+board) and a serial port on the Unix system. In the following, we
+assume you've hooked the cable between the PC's @file{COM1} port and
+@file{/dev/ttya} on the Unix system.
+
+@menu
+* Comms (EB29K):: Communications setup
+* gdb-EB29K:: EB29K cross-debugging
+* Remote Log:: Remote log
+@end menu
+
+@node Comms (EB29K)
+@subsubsection Communications setup
+
+The next step is to set up the PC's port, by doing something like this
+in DOS on the PC:
+
+@example
+C:\> MODE com1:9600,n,8,1,none
+@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:
+
+@example
+C:\> CTTY com1
+@end example
+
+@noindent
+(Later, if you wish to return control to the DOS console, you can use
+the command @code{CTTY con}---but you must send it over the device that
+had control, in our example over the @file{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:
+
+@example
+tip -9600 /dev/ttya
+@end example
+
+@noindent
+Your system may require a different name where we show
+@file{/dev/ttya} as the argument to @code{tip}. The communications
+parameters, including which 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 @code{tip} or @code{cu} connection, change the DOS working
+directory to the directory containing a copy of your 29K program, then
+start the PC program @code{EBMON} (an EB29K control program supplied
+with your board by AMD). You should see an initial display from
+@code{EBMON} similar to the one that follows, ending with the
+@code{EBMON} prompt @samp{#}---
+
+@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
+
+# ~.
+@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 @value{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 do not 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; @value{GDBN} will @emph{not} download it over the
+serial line.
+
+@node gdb-EB29K
+@subsubsection EB29K cross-debugging
+
+Finally, @code{cd} to the directory containing an image of your 29K
+program on the Unix system, and start @value{GDBN}---specifying as argument the
+name of your 29K program:
+
+@example
+cd /usr/joe/work29k
+@value{GDBP} myfoo
+@end example
+
+Now you can use the @code{target} command:
+
+@example
+target amd-eb /dev/ttya 9600 MYFOO
+@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
+@end example
+
+@noindent
+In this example, we've assumed your program is in a file called
+@file{myfoo}. Note that the filename given as the last argument to
+@code{target amd-eb} should be the name of the program as it appears to DOS.
+In our example this is simply @code{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 are ready
+to see your program run on the 29K board, use the @value{GDBN} command
+@code{run}.
+
+To stop debugging the remote program, use the @value{GDBN} @code{detach}
+command.
+
+To return control of the PC to its console, use @code{tip} or @code{cu}
+once again, after your @value{GDBN} session has concluded, to attach to
+@code{EBMON}. You can then type the command @code{q} to shut down
+@code{EBMON}, returning control to the DOS command-line interpreter.
+Type @code{CTTY con} to return command input to the main DOS console,
+and type @kbd{~.} to leave @code{tip} or @code{cu}.
+
+@node Remote Log
+@subsubsection Remote log
+@kindex eb.log
+@cindex log file for EB29K
+
+The @code{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 understand trouble with @code{EBMON}, or
+unexpected events on the PC side of the connection.
+
+@end ifset
+
+@ifset ST2000
+@node ST2000 Remote
+@subsection @value{GDBN} with a Tandem ST2000
+
+To connect your ST2000 to the host system, see the manufacturer's
+manual. Once the ST2000 is physically attached, you can run
+
+@example
+target st2000 @var{dev} @var{speed}
+@end example
+
+@noindent
+to establish it as your debugging environment. @var{dev} is normally
+the name of a serial device, such as @file{/dev/ttya}, connected to the
+ST2000 via a serial line. You can instead specify @var{dev} as a TCP
+connection (for example, to a serial line attached via a terminal
+concentrator) using the syntax @code{@var{hostname}:@var{portnumber}}.
+
+The @code{load} and @code{attach} commands are @emph{not} defined for
+this target; you must load your program into the ST2000 as you normally
+would for standalone operation. @value{GDBN} will read debugging information
+(such as symbols) from a separate, debugging version of the program
+available on your host computer.
+@c FIXME!! This is terribly vague; what little content is here is
+@c basically hearsay.
+
+@cindex ST2000 auxiliary commands
+These auxiliary @value{GDBN} commands are available to help you with the ST2000
+environment:
+
+@table @code
+@item st2000 @var{command}
+@kindex st2000 @var{cmd}
+@cindex STDBUG commands (ST2000)
+@cindex commands to STDBUG (ST2000)
+Send a @var{command} to the STDBUG monitor. See the manufacturer's
+manual for available commands.
+
+@item connect
+@cindex connect (to STDBUG)
+Connect the controlling terminal to the STDBUG command monitor. When
+you are done interacting with STDBUG, typing either of two character
+sequences will get you back to the @value{GDBN} command prompt:
+@kbd{@key{RET}~.} (Return, followed by tilde and period) or
+@kbd{@key{RET}~@key{C-d}} (Return, followed by tilde and control-D).
+@end table
+@end ifset
+
+@ifset VXWORKS
+@node VxWorks Remote
+@subsection @value{GDBN} and VxWorks
+@cindex VxWorks
+
+@value{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. @value{GDBN} uses code that runs on
+both the Unix host and on the VxWorks target. The program
+@code{gdb} is installed and executed on the Unix host. (It may be
+installed with the name @code{vxgdb}, to distinguish it from a
+@value{GDBN} for debugging programs on the host itself.)
+
+The following information on connecting to VxWorks was current when
+this manual was produced; newer releases of VxWorks may use revised
+procedures.
+
+The remote debugging interface (RDB) routines are installed and executed
+on the VxWorks target. These routines are included in the VxWorks library
+@file{rdb.a} and are incorporated into the system image when source-level
+debugging is enabled in the VxWorks configuration.
+
+@kindex INCLUDE_RDB
+If you wish, you can define @code{INCLUDE_RDB} in the VxWorks
+configuration file @file{configAll.h} to include the RDB interface
+routines and spawn the source debugging task @code{tRdbTask} when
+VxWorks is booted. For more information on configuring and remaking
+VxWorks, see the manufacturer's manual.
+@c VxWorks, see the @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 @value{GDBN}, you are ready
+to run @value{GDBN}. From your Unix host, run @code{gdb} (or
+@code{vxgdb}, depending on your installation).
+
+@value{GDBN} comes up showing the prompt:
+
+@example
+(vxgdb)
+@end example
+
+@menu
+* VxWorks Connection:: Connecting to VxWorks
+* VxWorks Download:: VxWorks download
+* VxWorks Attach:: Running tasks
+@end menu
+
+@node VxWorks Connection
+@subsubsection Connecting to VxWorks
+
+The @value{GDBN} command @code{target} lets you connect to a VxWorks target on the
+network. To connect to a target whose host name is ``@code{tt}'', type:
+
+@example
+(vxgdb) target vxworks tt
+@end example
+
+@value{GDBN} displays messages like these:
+
+@smallexample
+Attaching remote machine across net...
+Connected to tt.
+@end smallexample
+
+@value{GDBN} then attempts to read the symbol tables of any object modules
+loaded into the VxWorks target since it was last booted. @value{GDBN} locates
+these files by searching the directories listed in the command search
+path (@pxref{Environment, ,Your program's environment}); if it fails
+to find an object file, it displays a message such as:
+
+@example
+prog.o: No such file or directory.
+@end example
+
+When this happens, add the appropriate directory to the search path with
+the @value{GDBN} command @code{path}, and execute the @code{target}
+command again.
+
+@node VxWorks Download
+@subsubsection VxWorks download
+
+@cindex download 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 @value{GDBN}
+@code{load} command to download a file from Unix to VxWorks
+incrementally. The object file given as an argument to the @code{load}
+command is actually opened twice: first by the VxWorks target in order
+to download the code, then by @value{GDBN} in order to read the symbol
+table. This can lead to problems if the current working directories on
+the two systems differ. If both systems have NFS mounted the same
+filesystems, you can avoid these problems by using absolute paths.
+Otherwise, 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. For instance, a program
+@file{prog.o} may reside in @file{@var{vxpath}/vw/demo/rdb} in VxWorks
+and in @file{@var{hostpath}/vw/demo/rdb} on the host. To load this
+program, type this on VxWorks:
+
+@example
+-> cd "@var{vxpath}/vw/demo/rdb"
+@end example
+
+Then, in @value{GDBN}, type:
+
+@example
+(vxgdb) cd @var{hostpath}/vw/demo/rdb
+(vxgdb) load prog.o
+@end example
+
+@value{GDBN} displays a response similar to this:
+
+@smallexample
+Reading symbol data from wherever/vw/demo/rdb/prog.o... done.
+@end smallexample
+
+You can also use the @code{load} command to reload an object module
+after editing and recompiling the corresponding source file. Note that
+this will cause @value{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
+
+@cindex running VxWorks tasks
+You can also attach to an existing task using the @code{attach} command as
+follows:
+
+@example
+(vxgdb) attach @var{task}
+@end example
+
+@noindent
+where @var{task} 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.
+@end ifset
+
+@ifset H8
+@node Hitachi Remote
+@subsection @value{GDBN} and Hitachi Microprocessors
+@value{GDBN} needs to know these things to talk to your
+Hitachi SH, H8/300, or H8/500:
+
+@enumerate
+@item
+that you want to use @samp{target hms}, the remote debugging interface
+for Hitachi microprocessors (this is the default when GDB is configured
+specifically for the Hitachi SH, H8/300, or H8/500);
+
+@item
+what serial device connects your host to your Hitachi board (the first
+serial device available on your host is the default);
+
+@ignore
+@c this is only for Unix hosts, not currently of interest.
+@item
+what speed to use over the serial device.
+@end ignore
+@end enumerate
+
+@ifclear H8EXCLUSIVE
+@c only for Unix hosts
+@kindex device
+@cindex serial device, Hitachi micros
+Use the special @code{@value{GDBP}} command @samp{device @var{port}} if you
+need to explicitly set the serial device. The default @var{port} is the
+first available port on your host. This is only necessary on Unix
+hosts, where it is typically something like @file{/dev/ttya}.
+
+@kindex speed
+@cindex serial line speed, Hitachi micros
+@code{@value{GDBP}} has another special command to set the communications
+speed: @samp{speed @var{bps}}. This command also is only used from Unix
+hosts; on DOS hosts, set the line speed as usual from outside GDB with
+the DOS @kbd{mode} command (for instance, @w{@samp{mode
+com2:9600,n,8,1,p}} for a 9600 bps connection).
+
+The @samp{device} and @samp{speed} commands are available only when you
+use a Unix host to debug your Hitachi microprocessor programs. If you
+use a DOS host,
+@end ifclear
+@value{GDBN} depends on an auxiliary terminate-and-stay-resident program
+called @code{asynctsr} to communicate with the development board
+through a PC serial port. You must also use the DOS @code{mode} command
+to set up the serial port on the DOS side.
+
+@ifset DOSHOST
+The following sample session illustrates the steps needed to start a
+program under @value{GDBN} control on an H8/300. The example uses a
+sample H8/300 program called @file{t.x}. The procedure is the same for
+the Hitachi SH and the H8/500.
+
+First hook up your development board. In this example, we use a
+board attached to serial port @code{COM2}; if you use a different serial
+port, substitute its name in the argument of the @code{mode} command.
+When you call @code{asynctsr}, the auxiliary comms program used by the
+degugger, you give it just the numeric part of the serial port's name;
+for example, @samp{asyncstr 2} below runs @code{asyncstr} on
+@code{COM2}.
+
+@example
+(eg-C:\H8300\TEST) mode com2:9600,n,8,1,p
+
+Resident portion of MODE loaded
+
+COM2: 9600, n, 8, 1, p
+
+(eg-C:\H8300\TEST) asynctsr 2
+@end example
+
+@quotation
+@emph{Warning:} We have noticed a bug in PC-NFS that conflicts with
+@code{asynctsr}. If you also run PC-NFS on your DOS host, you may need to
+disable it, or even boot without it, to use @code{asynctsr} to control
+your development board.
+@end quotation
+
+@kindex target hms
+Now that serial communications are set up, and the development board is
+connected, you can start up @value{GDBN}. Call @code{@value{GDBP}} with
+the name of your program as the argument. @code{@value{GDBP}} prompts
+you, as usual, with the prompt @samp{(@value{GDBP})}. Use two special
+commands to begin your debugging session: @samp{target hms} to specify
+cross-debugging to the Hitachi board, and the @code{load} command to
+download your program to the board. @code{load} displays the names of
+the program's sections, and a @samp{*} for each 2K of data downloaded.
+(If you want to refresh @value{GDBN} data on symbols or on the
+executable file without downloading, use the @value{GDBN} commands
+@code{file} or @code{symbol-file}. These commands, and @code{load}
+itself, are described in @ref{Files,,Commands to specify files}.)
+
+@smallexample
+(eg-C:\H8300\TEST) @value{GDBP} t.x
+GDB is free software and you are welcome to distribute copies
+ of it under certain conditions; type "show copying" to see
+ the conditions.
+There is absolutely no warranty for GDB; type "show warranty"
+for details.
+GDB @value{GDBVN}, Copyright 1992 Free Software Foundation, Inc...
+(gdb) target hms
+Connected to remote H8/300 HMS system.
+(gdb) load t.x
+.text : 0x8000 .. 0xabde ***********
+.data : 0xabde .. 0xad30 *
+.stack : 0xf000 .. 0xf014 *
+@end smallexample
+
+At this point, you're ready to run or debug your program. From here on,
+you can use all the usual @value{GDBN} commands. The @code{break} command
+sets breakpoints; the @code{run} command starts your program;
+@code{print} or @code{x} display data; the @code{continue} command
+resumes execution after stopping at a breakpoint. You can use the
+@code{help} command at any time to find out more about @value{GDBN} commands.
+
+Remember, however, that @emph{operating system} facilities aren't
+available on your development board; for example, if your program hangs,
+you can't send an interrupt---but you can press the @sc{reset} switch!
+
+Use the @sc{reset} button on the development board
+@itemize @bullet
+@item
+to interrupt your program (don't use @kbd{ctl-C} on the DOS host---it has
+no way to pass an interrupt signal to the development board); and
+
+@item
+to return to the @value{GDBN} command prompt after your program finishes
+normally. The communications protocol provides no other way for @value{GDBN}
+to detect program completion.
+@end itemize
+
+In either case, @value{GDBN} will see the effect of a @sc{reset} on the
+development board as a ``normal exit'' of your program.
+@end ifset
+@end ifset
+
+@ifset MIPS
+@node MIPS Remote
+@subsection @value{GDBN} and remote MIPS boards
+
+@cindex MIPS boards
+@value{GDBN} can use the MIPS remote debugging protocol to talk to a
+MIPS board attached to a serial line. This is available when
+you configure @value{GDBN} with @samp{--target=mips-idt-ecoff}.
+
+@kindex target mips @var{port}
+To run a program on the board, start up @code{@value{GDBP}} with the
+name of your program as the argument. To connect to the board, use the
+command @samp{target mips @var{port}}, where @var{port} is the name of
+the serial port connected to the board. If the program has not already
+been downloaded to the board, you may use the @code{load} command to
+download it. You can then use all the usual @value{GDBN} commands.
+
+You can also specify @var{port} as a TCP connection (for instance, to a
+serial line managed by a terminal concentrator), using the syntax
+@code{@var{hostname}:@var{portnumber}}.
+
+@cindex @code{remotedebug}, MIPS protocol
+@c FIXME! For this to be useful, you must know something about the MIPS
+@c FIXME...protocol. Where is it described?
+You can see some debugging information about communications with the board
+by setting the @code{remotedebug} variable. If you set it to 1 using
+@samp{set remotedebug 1} every packet will be displayed. If you set it
+to 2 every character will be displayed. You can check the current value
+at any time with the command @samp{show remotedebug}.
+
+@cindex @code{timeout}, MIPS protocol
+@cindex @code{retransmit-timeout}, MIPS protocol
+@kindex set timeout
+@kindex show timeout
+@kindex set retransmit-timeout
+@kindex show retransmit-timeout
+You can control the timeout used while waiting for a packet, in the MIPS
+remote protocol, with the @code{set timeout @var{seconds}} command. The
+default is 5 seconds. Similarly, you can control the timeout used while
+waiting for an acknowledgement of a packet with the @code{set
+retransmit-timeout @var{seconds}} command. The default is 3 seconds.
+You can inspect both values with @code{show timeout} and @code{show
+retransmit-timeout}. (These commands are @emph{only} available when
+@value{GDBN} is configured for @samp{--target=mips-idt-ecoff}.)
+
+@kindex set mipsfpu off
+@cindex MIPS remote floating point
+@cindex floating point, MIPS remote
+If your target board does not support the MIPS floating point
+coprocessor, you should use the command @samp{set mipsfpu off} (you may
+wish to put this in your @value{GDBINIT} file). This tells @value{GDBN}
+how to find the return value of functions which return floating point
+values. It also allows @value{GDBN} to avoid saving the floating point
+registers when calling functions on the board.
+@end ifset
+
+@ifset SIMS
+@node Simulator
+@subsection Simulated CPU target
+
+@ifset GENERIC
+@cindex simulator
+@cindex simulator, Z8000
+@cindex Z8000 simulator
+@cindex simulator, H8/300 or H8/500
+@cindex H8/300 or H8/500 simulator
+@cindex simulator, Hitachi SH
+@cindex Hitachi SH simulator
+@cindex CPU simulator
+For some configurations, @value{GDBN} includes a CPU simulator that you
+can use instead of a hardware CPU to debug your programs. Currently,
+a simulator is available when @value{GDBN} is configured to debug Zilog
+Z8000 or Hitachi microprocessor targets.
+@end ifset
+
+@ifclear GENERIC
+@ifset H8
+@cindex simulator, H8/300 or H8/500
+@cindex Hitachi H8/300 or H8/500 simulator
+@cindex simulator, Hitachi SH
+@cindex Hitachi SH simulator
+When configured for debugging Hitachi microprocessor targets,
+@value{GDBN} includes a CPU simulator for the target chip (a Hitachi SH,
+H8/300, or H8/500).
+@end ifset
+
+@ifset Z8K
+@cindex simulator, Z8000
+@cindex Zilog Z8000 simulator
+When configured for debugging Zilog Z8000 targets, @value{GDBN} includes
+a Z8000 simulator.
+@end ifset
+@end ifclear
+
+@ifset Z8K
+For the Z8000 family, @samp{target sim} simulates either the Z8002 (the
+unsegmented variant of the Z8000 architecture) or the Z8001 (the
+segmented variant). The simulator recognizes which architecture is
+appropriate by inspecting the object code.
+@end ifset
+
+@table @code
+@item target sim
+@kindex sim
+@kindex target sim
+Debug programs on a simulated CPU
+@ifset GENERIC
+(which CPU depends on the @value{GDBN} configuration)
+@end ifset
+@end table
+
+@noindent
+After specifying this target, you can debug programs for the simulated
+CPU in the same style as programs for your host computer; use the
+@code{file} command to load a new program image, the @code{run} command
+to run your program, and so on.
+
+As well as making available all the usual machine registers (see
+@code{info reg}), this debugging target provides three additional items
+of information as specially named registers:
+
+@table @code
+@item cycles
+Counts clock-ticks in the simulator.
+
+@item insts
+Counts instructions run in the simulator.
+
+@item time
+Execution time in 60ths of a second.
+@end table
+
+You can refer to these values in @value{GDBN} expressions with the usual
+conventions; for example, @w{@samp{b fputc if $cycles>5000}} sets a
+conditional breakpoint that will suspend only after at least 5000
+simulated clock ticks.
+@end ifset
diff --git a/gnu/usr.bin/gdb/doc/stabs.texinfo b/gnu/usr.bin/gdb/doc/stabs.texinfo
new file mode 100644
index 000000000000..41b29819d551
--- /dev/null
+++ b/gnu/usr.bin/gdb/doc/stabs.texinfo
@@ -0,0 +1,3795 @@
+\input texinfo
+@setfilename stabs.info
+
+@c @finalout
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Stabs:: The "stabs" debugging information format.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+This document describes the stabs debugging symbol tables.
+
+Copyright 1992, 1993 Free Software Foundation, Inc.
+Contributed by Cygnus Support. Written by Julia Menapace, Jim Kingdon,
+and David MacKenzie.
+
+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 STABS
+@titlepage
+@title The ``stabs'' debug format
+@author Julia Menapace, Jim Kingdon, David MacKenzie
+@author Cygnus Support
+@page
+@tex
+\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision: 1.1 $} % 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{} 1992, 1993 Free Software Foundation, Inc.
+Contributed by Cygnus Support.
+
+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
+
+@ifinfo
+@node Top
+@top The "stabs" representation of debugging information
+
+This document describes the stabs debugging format.
+
+@menu
+* Overview:: Overview of stabs
+* Program Structure:: Encoding of the structure of the program
+* Constants:: Constants
+* Variables::
+* Types:: Type definitions
+* Symbol Tables:: Symbol information in symbol tables
+* Cplusplus:: Appendixes:
+* Stab Types:: Symbol types in a.out files
+* Symbol Descriptors:: Table of symbol descriptors
+* Type Descriptors:: Table of type descriptors
+* Expanded Reference:: Reference information by stab type
+* Questions:: Questions and anomolies
+* XCOFF Differences:: Differences between GNU stabs in a.out
+ and GNU stabs in XCOFF
+* Sun Differences:: Differences between GNU stabs and Sun
+ native stabs
+* Stabs In ELF:: Stabs in an ELF file.
+* Symbol Types Index:: Index of symbolic stab symbol type names.
+@end menu
+@end ifinfo
+
+
+@node Overview
+@chapter Overview of Stabs
+
+@dfn{Stabs} refers to a format for information that describes a program
+to a debugger. This format was apparently invented by
+@c FIXME! <<name of inventor>> at
+the University of California at Berkeley, for the @code{pdx} Pascal
+debugger; the format has spread widely since then.
+
+This document is one of the few published sources of documentation on
+stabs. It is believed to be comprehensive for stabs used by C. The
+lists of symbol descriptors (@pxref{Symbol Descriptors}) and type
+descriptors (@pxref{Type Descriptors}) are believed to be completely
+comprehensive. Stabs for COBOL-specific features and for variant
+records (used by Pascal and Modula-2) are poorly documented here.
+
+Other sources of information on stabs are @cite{Dbx and Dbxtool
+Interfaces}, 2nd edition, by Sun, 1988, and @cite{AIX Version 3.2 Files
+Reference}, Fourth Edition, September 1992, "dbx Stabstring Grammar" in
+the a.out section, page 2-31. This document is believed to incorporate
+the information from those two sources except where it explictly directs
+you to them for more information.
+
+@menu
+* Flow:: Overview of debugging information flow
+* Stabs Format:: Overview of stab format
+* String Field:: The string field
+* C Example:: A simple example in C source
+* Assembly Code:: The simple example at the assembly level
+@end menu
+
+@node Flow
+@section Overview of Debugging Information Flow
+
+The GNU C compiler compiles C source in a @file{.c} file into assembly
+language in a @file{.s} file, which the assembler translates into
+a @file{.o} file, which the linker combines with other @file{.o} files and
+libraries to produce an executable file.
+
+With the @samp{-g} option, GCC puts in the @file{.s} file additional
+debugging information, which is slightly transformed by the assembler
+and linker, and carried through into the final executable. This
+debugging information describes features of the source file like line
+numbers, the types and scopes of variables, and function names,
+parameters, and scopes.
+
+For some object file formats, the debugging information is encapsulated
+in assembler directives known collectively as @dfn{stab} (symbol table)
+directives, which are interspersed with the generated code. Stabs are
+the native format for debugging information in the a.out and XCOFF
+object file formats. The GNU tools can also emit stabs in the COFF and
+ECOFF object file formats.
+
+The assembler adds the information from stabs to the symbol information
+it places by default in the symbol table and the string table of the
+@file{.o} file it is building. The linker consolidates the @file{.o}
+files into one executable file, with one symbol table and one string
+table. Debuggers use the symbol and string tables in the executable as
+a source of debugging information about the program.
+
+@node Stabs Format
+@section Overview of Stab Format
+
+There are three overall formats for stab assembler directives,
+differentiated by the first word of the stab. The name of the directive
+describes which combination of four possible data fields follows. It is
+either @code{.stabs} (string), @code{.stabn} (number), or @code{.stabd}
+(dot). IBM's XCOFF assembler uses @code{.stabx} (and some other
+directives such as @code{.file} and @code{.bi}) instead of
+@code{.stabs}, @code{.stabn} or @code{.stabd}.
+
+The overall format of each class of stab is:
+
+@example
+.stabs "@var{string}",@var{type},@var{other},@var{desc},@var{value}
+.stabn @var{type},@var{other},@var{desc},@var{value}
+.stabd @var{type},@var{other},@var{desc}
+.stabx "@var{string}",@var{value},@var{type},@var{sdb-type}
+@end example
+
+@c what is the correct term for "current file location"? My AIX
+@c assembler manual calls it "the value of the current location counter".
+For @code{.stabn} and @code{.stabd}, there is no @var{string} (the
+@code{n_strx} field is zero; see @ref{Symbol Tables}). For
+@code{.stabd}, the @var{value} field is implicit and has the value of
+the current file location. For @code{.stabx}, the @var{sdb-type} field
+is unused for stabs and can always be set to zero. The @var{other}
+field is almost always unused and can be set to zero.
+
+The number in the @var{type} field gives some basic information about
+which type of stab this is (or whether it @emph{is} a stab, as opposed
+to an ordinary symbol). Each valid type number defines a different stab
+type; further, the stab type defines the exact interpretation of, and
+possible values for, any remaining @var{string}, @var{desc}, or
+@var{value} fields present in the stab. @xref{Stab Types}, for a list
+in numeric order of the valid @var{type} field values for stab directives.
+
+@node String Field
+@section The String Field
+
+For most stabs the string field holds the meat of the
+debugging information. The flexible nature of this field
+is what makes stabs extensible. For some stab types the string field
+contains only a name. For other stab types the contents can be a great
+deal more complex.
+
+The overall format of the string field for most stab types is:
+
+@example
+"@var{name}:@var{symbol-descriptor} @var{type-information}"
+@end example
+
+@var{name} is the name of the symbol represented by the stab.
+@var{name} can be omitted, which means the stab represents an unnamed
+object. For example, @samp{:t10=*2} defines type 10 as a pointer to
+type 2, but does not give the type a name. Omitting the @var{name}
+field is supported by AIX dbx and GDB after about version 4.8, but not
+other debuggers. GCC sometimes uses a single space as the name instead
+of omitting the name altogether; apparently that is supported by most
+debuggers.
+
+The @var{symbol-descriptor} following the @samp{:} is an alphabetic
+character that tells more specifically what kind of symbol the stab
+represents. If the @var{symbol-descriptor} is omitted, but type
+information follows, then the stab represents a local variable. For a
+list of symbol descriptors, see @ref{Symbol Descriptors}. The @samp{c}
+symbol descriptor is an exception in that it is not followed by type
+information. @xref{Constants}.
+
+@var{type-information} is either a @var{type-number}, or
+@samp{@var{type-number}=}. A @var{type-number} alone is a type
+reference, referring directly to a type that has already been defined.
+
+The @samp{@var{type-number}=} form is a type definition, where the
+number represents a new type which is about to be defined. The type
+definition may refer to other types by number, and those type numbers
+may be followed by @samp{=} and nested definitions.
+
+In a type definition, if the character that follows the equals sign is
+non-numeric then it is a @var{type-descriptor}, and tells what kind of
+type is about to be defined. Any other values following the
+@var{type-descriptor} vary, depending on the @var{type-descriptor}.
+@xref{Type Descriptors}, for a list of @var{type-descriptor} values. If
+a number follows the @samp{=} then the number is a @var{type-reference}.
+For a full description of types, @ref{Types}.
+
+There is an AIX extension for type attributes. Following the @samp{=}
+are any number of type attributes. Each one starts with @samp{@@} and
+ends with @samp{;}. Debuggers, including AIX's dbx and GDB 4.10, skip
+any type attributes they do not recognize. GDB 4.9 and other versions
+of dbx may not do this. Because of a conflict with C++
+(@pxref{Cplusplus}), new attributes should not be defined which begin
+with a digit, @samp{(}, or @samp{-}; GDB may be unable to distinguish
+those from the C++ type descriptor @samp{@@}. The attributes are:
+
+@table @code
+@item a@var{boundary}
+@var{boundary} is an integer specifying the alignment. I assume it
+applies to all variables of this type.
+
+@item s@var{size}
+Size in bits of a variable of this type.
+
+@item p@var{integer}
+Pointer class (for checking). Not sure what this means, or how
+@var{integer} is interpreted.
+
+@item P
+Indicate this is a packed type, meaning that structure fields or array
+elements are placed more closely in memory, to save memory at the
+expense of speed.
+@end table
+
+All of this can make the string field quite long. All
+versions of GDB, and some versions of dbx, can handle arbitrarily long
+strings. But many versions of dbx cretinously limit the strings to
+about 80 characters, so compilers which must work with such dbx's need
+to split the @code{.stabs} directive into several @code{.stabs}
+directives. Each stab duplicates exactly all but the
+string field. The string field of
+every stab except the last is marked as continued with a
+double-backslash at the end. Removing the backslashes and concatenating
+the string fields of each stab produces the original,
+long string.
+
+@node C Example
+@section A Simple Example in C Source
+
+To get the flavor of how stabs describe source information for a C
+program, let's look at the simple program:
+
+@example
+main()
+@{
+ printf("Hello world");
+@}
+@end example
+
+When compiled with @samp{-g}, the program above yields the following
+@file{.s} file. Line numbers have been added to make it easier to refer
+to parts of the @file{.s} file in the description of the stabs that
+follows.
+
+@node Assembly Code
+@section The Simple Example at the Assembly Level
+
+This simple ``hello world'' example demonstrates several of the stab
+types used to describe C language source files.
+
+@example
+1 gcc2_compiled.:
+2 .stabs "/cygint/s1/users/jcm/play/",100,0,0,Ltext0
+3 .stabs "hello.c",100,0,0,Ltext0
+4 .text
+5 Ltext0:
+6 .stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
+7 .stabs "char:t2=r2;0;127;",128,0,0,0
+8 .stabs "long int:t3=r1;-2147483648;2147483647;",128,0,0,0
+9 .stabs "unsigned int:t4=r1;0;-1;",128,0,0,0
+10 .stabs "long unsigned int:t5=r1;0;-1;",128,0,0,0
+11 .stabs "short int:t6=r1;-32768;32767;",128,0,0,0
+12 .stabs "long long int:t7=r1;0;-1;",128,0,0,0
+13 .stabs "short unsigned int:t8=r1;0;65535;",128,0,0,0
+14 .stabs "long long unsigned int:t9=r1;0;-1;",128,0,0,0
+15 .stabs "signed char:t10=r1;-128;127;",128,0,0,0
+16 .stabs "unsigned char:t11=r1;0;255;",128,0,0,0
+17 .stabs "float:t12=r1;4;0;",128,0,0,0
+18 .stabs "double:t13=r1;8;0;",128,0,0,0
+19 .stabs "long double:t14=r1;8;0;",128,0,0,0
+20 .stabs "void:t15=15",128,0,0,0
+21 .align 4
+22 LC0:
+23 .ascii "Hello, world!\12\0"
+24 .align 4
+25 .global _main
+26 .proc 1
+27 _main:
+28 .stabn 68,0,4,LM1
+29 LM1:
+30 !#PROLOGUE# 0
+31 save %sp,-136,%sp
+32 !#PROLOGUE# 1
+33 call ___main,0
+34 nop
+35 .stabn 68,0,5,LM2
+36 LM2:
+37 LBB2:
+38 sethi %hi(LC0),%o1
+39 or %o1,%lo(LC0),%o0
+40 call _printf,0
+41 nop
+42 .stabn 68,0,6,LM3
+43 LM3:
+44 LBE2:
+45 .stabn 68,0,6,LM4
+46 LM4:
+47 L1:
+48 ret
+49 restore
+50 .stabs "main:F1",36,0,0,_main
+51 .stabn 192,0,0,LBB2
+52 .stabn 224,0,0,LBE2
+@end example
+
+@node Program Structure
+@chapter Encoding the Structure of the Program
+
+The elements of the program structure that stabs encode include the name
+of the main function, the names of the source and include files, the
+line numbers, procedure names and types, and the beginnings and ends of
+blocks of code.
+
+@menu
+* Main Program:: Indicate what the main program is
+* Source Files:: The path and name of the source file
+* Include Files:: Names of include files
+* Line Numbers::
+* Procedures::
+* Nested Procedures::
+* Block Structure::
+@end menu
+
+@node Main Program
+@section Main Program
+
+@findex N_MAIN
+Most languages allow the main program to have any name. The
+@code{N_MAIN} stab type tells the debugger the name that is used in this
+program. Only the string field is significant; it is the name of
+a function which is the main program. Most C compilers do not use this
+stab (they expect the debugger to assume that the name is @code{main}),
+but some C compilers emit an @code{N_MAIN} stab for the @code{main}
+function.
+
+@node Source Files
+@section Paths and Names of the Source Files
+
+@findex N_SO
+Before any other stabs occur, there must be a stab specifying the source
+file. This information is contained in a symbol of stab type
+@code{N_SO}; the string field contains the name of the file. The
+value of the symbol is the start address of the portion of the
+text section corresponding to that file.
+
+With the Sun Solaris2 compiler, the desc field contains a
+source-language code.
+@c Do the debuggers use it? What are the codes? -djm
+
+Some compilers (for example, GCC2 and SunOS4 @file{/bin/cc}) also
+include the directory in which the source was compiled, in a second
+@code{N_SO} symbol preceding the one containing the file name. This
+symbol can be distinguished by the fact that it ends in a slash. Code
+from the @code{cfront} C++ compiler can have additional @code{N_SO} symbols for
+nonexistent source files after the @code{N_SO} for the real source file;
+these are believed to contain no useful information.
+
+For example:
+
+@example
+.stabs "/cygint/s1/users/jcm/play/",100,0,0,Ltext0 # @r{100 is N_SO}
+.stabs "hello.c",100,0,0,Ltext0
+ .text
+Ltext0:
+@end example
+
+Instead of @code{N_SO} symbols, XCOFF uses a @code{.file} assembler
+directive which assembles to a standard COFF @code{.file} symbol;
+explaining this in detail is outside the scope of this document.
+
+@node Include Files
+@section Names of Include Files
+
+There are several schemes for dealing with include files: the
+traditional @code{N_SOL} approach, Sun's @code{N_BINCL} approach, and the
+XCOFF @code{C_BINCL} approach (which despite the similar name has little in
+common with @code{N_BINCL}).
+
+@findex N_SOL
+An @code{N_SOL} symbol specifies which include file subsequent symbols
+refer to. The string field is the name of the file and the value is the
+text address corresponding to the end of the previous include file and
+the start of this one. To specify the main source file again, use an
+@code{N_SOL} symbol with the name of the main source file.
+
+@findex N_BINCL
+@findex N_EINCL
+@findex N_EXCL
+The @code{N_BINCL} approach works as follows. An @code{N_BINCL} symbol
+specifies the start of an include file. In an object file, only the
+string is significant; the Sun linker puts data into some of the
+other fields. The end of the include file is marked by an
+@code{N_EINCL} symbol (which has no string field). In an object
+file, there is no significant data in the @code{N_EINCL} symbol; the Sun
+linker puts data into some of the fields. @code{N_BINCL} and
+@code{N_EINCL} can be nested.
+
+If the linker detects that two source files have identical stabs between
+an @code{N_BINCL} and @code{N_EINCL} pair (as will generally be the case
+for a header file), then it only puts out the stabs once. Each
+additional occurance is replaced by an @code{N_EXCL} symbol. I believe
+the Sun (SunOS4, not sure about Solaris) linker is the only one which
+supports this feature.
+@c What do the fields of N_EXCL contain? -djm
+
+@findex C_BINCL
+@findex C_EINCL
+For the start of an include file in XCOFF, use the @file{.bi} assembler
+directive, which generates a @code{C_BINCL} symbol. A @file{.ei}
+directive, which generates a @code{C_EINCL} symbol, denotes the end of
+the include file. Both directives are followed by the name of the
+source file in quotes, which becomes the string for the symbol.
+The value of each symbol, produced automatically by the assembler
+and linker, is the offset into the executable of the beginning
+(inclusive, as you'd expect) or end (inclusive, as you would not expect)
+of the portion of the COFF line table that corresponds to this include
+file. @code{C_BINCL} and @code{C_EINCL} do not nest.
+
+@node Line Numbers
+@section Line Numbers
+
+@findex N_SLINE
+An @code{N_SLINE} symbol represents the start of a source line. The
+desc field contains the line number and the value
+contains the code address for the start of that source line. On most
+machines the address is absolute; for Sun's stabs-in-ELF, it is relative
+to the function in which the @code{N_SLINE} symbol occurs.
+
+@findex N_DSLINE
+@findex N_BSLINE
+GNU documents @code{N_DSLINE} and @code{N_BSLINE} symbols for line
+numbers in the data or bss segments, respectively. They are identical
+to @code{N_SLINE} but are relocated differently by the linker. They
+were intended to be used to describe the source location of a variable
+declaration, but I believe that GCC2 actually puts the line number in
+the desc field of the stab for the variable itself. GDB has been
+ignoring these symbols (unless they contain a string field) since
+at least GDB 3.5.
+
+For single source lines that generate discontiguous code, such as flow
+of control statements, there may be more than one line number entry for
+the same source line. In this case there is a line number entry at the
+start of each code range, each with the same line number.
+
+XCOFF does not use stabs for line numbers. Instead, it uses COFF line
+numbers (which are outside the scope of this document). Standard COFF
+line numbers cannot deal with include files, but in XCOFF this is fixed
+with the @code{C_BINCL} method of marking include files (@pxref{Include
+Files}).
+
+@node Procedures
+@section Procedures
+
+@findex N_FUN, for functions
+@findex N_FNAME
+@findex N_STSYM, for functions (Sun acc)
+@findex N_GSYM, for functions (Sun acc)
+All of the following stabs normally use the @code{N_FUN} symbol type.
+However, Sun's @code{acc} compiler on SunOS4 uses @code{N_GSYM} and
+@code{N_STSYM}, which means that the value of the stab for the function
+is useless and the debugger must get the address of the function from
+the non-stab symbols instead. BSD Fortran is said to use @code{N_FNAME}
+with the same restriction; the value of the symbol is not useful (I'm
+not sure it really does use this, because GDB doesn't handle this and no
+one has complained).
+
+A function is represented by an @samp{F} symbol descriptor for a global
+(extern) function, and @samp{f} for a static (local) function. The
+value is the address of the start of the function. For @code{a.out}, it
+is already relocated. For stabs in ELF, the SunPRO compiler version
+2.0.1 and GCC put out an address which gets relocated by the linker. In
+a future release SunPRO is planning to put out zero, in which case the
+address can be found from the ELF (non-stab) symbol. Because looking
+things up in the ELF symbols would probably be slow, I'm not sure how to
+find which symbol of that name is the right one, and this doesn't
+provide any way to deal with nested functions, it would probably be
+better to make the value of the stab an address relative to the start of
+the file. See @ref{Stabs In ELF} for more information on linker
+relocation of stabs in ELF files.
+
+The type information of the stab represents the return type of the
+function; thus @samp{foo:f5} means that foo is a function returning type
+5. There is no need to try to get the line number of the start of the
+function from the stab for the function; it is in the next
+@code{N_SLINE} symbol.
+
+@c FIXME: verify whether the "I suspect" below is true or not.
+Some compilers (such as Sun's Solaris compiler) support an extension for
+specifying the types of the arguments. I suspect this extension is not
+used for old (non-prototyped) function definitions in C. If the
+extension is in use, the type information of the stab for the function
+is followed by type information for each argument, with each argument
+preceded by @samp{;}. An argument type of 0 means that additional
+arguments are being passed, whose types and number may vary (@samp{...}
+in ANSI C). GDB has tolerated this extension (parsed the syntax, if not
+necessarily used the information) since at least version 4.8; I don't
+know whether all versions of dbx tolerate it. The argument types given
+here are not redundant with the symbols for the formal parameters
+(@pxref{Parameters}); they are the types of the arguments as they are
+passed, before any conversions might take place. For example, if a C
+function which is declared without a prototype takes a @code{float}
+argument, the value is passed as a @code{double} but then converted to a
+@code{float}. Debuggers need to use the types given in the arguments
+when printing values, but when calling the function they need to use the
+types given in the symbol defining the function.
+
+If the return type and types of arguments of a function which is defined
+in another source file are specified (i.e., a function prototype in ANSI
+C), traditionally compilers emit no stab; the only way for the debugger
+to find the information is if the source file where the function is
+defined was also compiled with debugging symbols. As an extension the
+Solaris compiler uses symbol descriptor @samp{P} followed by the return
+type of the function, followed by the arguments, each preceded by
+@samp{;}, as in a stab with symbol descriptor @samp{f} or @samp{F}.
+This use of symbol descriptor @samp{P} can be distinguished from its use
+for register parameters (@pxref{Register Parameters}) by the fact that it has
+symbol type @code{N_FUN}.
+
+The AIX documentation also defines symbol descriptor @samp{J} as an
+internal function. I assume this means a function nested within another
+function. It also says symbol descriptor @samp{m} is a module in
+Modula-2 or extended Pascal.
+
+Procedures (functions which do not return values) are represented as
+functions returning the @code{void} type in C. I don't see why this couldn't
+be used for all languages (inventing a @code{void} type for this purpose if
+necessary), but the AIX documentation defines @samp{I}, @samp{P}, and
+@samp{Q} for internal, global, and static procedures, respectively.
+These symbol descriptors are unusual in that they are not followed by
+type information.
+
+The following example shows a stab for a function @code{main} which
+returns type number @code{1}. The @code{_main} specified for the value
+is a reference to an assembler label which is used to fill in the start
+address of the function.
+
+@example
+.stabs "main:F1",36,0,0,_main # @r{36 is N_FUN}
+@end example
+
+The stab representing a procedure is located immediately following the
+code of the procedure. This stab is in turn directly followed by a
+group of other stabs describing elements of the procedure. These other
+stabs describe the procedure's parameters, its block local variables, and
+its block structure.
+
+@node Nested Procedures
+@section Nested Procedures
+
+For any of the symbol descriptors representing procedures, after the
+symbol descriptor and the type information is optionally a scope
+specifier. This consists of a comma, the name of the procedure, another
+comma, and the name of the enclosing procedure. The first name is local
+to the scope specified, and seems to be redundant with the name of the
+symbol (before the @samp{:}). This feature is used by GCC, and
+presumably Pascal, Modula-2, etc., compilers, for nested functions.
+
+If procedures are nested more than one level deep, only the immediately
+containing scope is specified. For example, this code:
+
+@example
+int
+foo (int x)
+@{
+ int bar (int y)
+ @{
+ int baz (int z)
+ @{
+ return x + y + z;
+ @}
+ return baz (x + 2 * y);
+ @}
+ return x + bar (3 * x);
+@}
+@end example
+
+@noindent
+produces the stabs:
+
+@example
+.stabs "baz:f1,baz,bar",36,0,0,_baz.15 # @r{36 is N_FUN}
+.stabs "bar:f1,bar,foo",36,0,0,_bar.12
+.stabs "foo:F1",36,0,0,_foo
+@end example
+
+@node Block Structure
+@section Block Structure
+
+@findex N_LBRAC
+@findex N_RBRAC
+The program's block structure is represented by the @code{N_LBRAC} (left
+brace) and the @code{N_RBRAC} (right brace) stab types. The variables
+defined inside a block precede the @code{N_LBRAC} symbol for most
+compilers, including GCC. Other compilers, such as the Convex, Acorn
+RISC machine, and Sun @code{acc} compilers, put the variables after the
+@code{N_LBRAC} symbol. The values of the @code{N_LBRAC} and
+@code{N_RBRAC} symbols are the start and end addresses of the code of
+the block, respectively. For most machines, they are relative to the
+starting address of this source file. For the Gould NP1, they are
+absolute. For Sun's stabs-in-ELF, they are relative to the function in
+which they occur.
+
+The @code{N_LBRAC} and @code{N_RBRAC} stabs that describe the block
+scope of a procedure are located after the @code{N_FUN} stab that
+represents the procedure itself.
+
+Sun documents the desc field of @code{N_LBRAC} and
+@code{N_RBRAC} symbols as containing the nesting level of the block.
+However, dbx seems to not care, and GCC always sets desc to
+zero.
+
+@node Constants
+@chapter Constants
+
+The @samp{c} symbol descriptor indicates that this stab represents a
+constant. This symbol descriptor is an exception to the general rule
+that symbol descriptors are followed by type information. Instead, it
+is followed by @samp{=} and one of the following:
+
+@table @code
+@item b @var{value}
+Boolean constant. @var{value} is a numeric value; I assume it is 0 for
+false or 1 for true.
+
+@item c @var{value}
+Character constant. @var{value} is the numeric value of the constant.
+
+@item e @var{type-information} , @var{value}
+Constant whose value can be represented as integral.
+@var{type-information} is the type of the constant, as it would appear
+after a symbol descriptor (@pxref{String Field}). @var{value} is the
+numeric value of the constant. GDB 4.9 does not actually get the right
+value if @var{value} does not fit in a host @code{int}, but it does not
+do anything violent, and future debuggers could be extended to accept
+integers of any size (whether unsigned or not). This constant type is
+usually documented as being only for enumeration constants, but GDB has
+never imposed that restriction; I don't know about other debuggers.
+
+@item i @var{value}
+Integer constant. @var{value} is the numeric value. The type is some
+sort of generic integer type (for GDB, a host @code{int}); to specify
+the type explicitly, use @samp{e} instead.
+
+@item r @var{value}
+Real constant. @var{value} is the real value, which can be @samp{INF}
+(optionally preceded by a sign) for infinity, @samp{QNAN} for a quiet
+NaN (not-a-number), or @samp{SNAN} for a signalling NaN. If it is a
+normal number the format is that accepted by the C library function
+@code{atof}.
+
+@item s @var{string}
+String constant. @var{string} is a string enclosed in either @samp{'}
+(in which case @samp{'} characters within the string are represented as
+@samp{\'} or @samp{"} (in which case @samp{"} characters within the
+string are represented as @samp{\"}).
+
+@item S @var{type-information} , @var{elements} , @var{bits} , @var{pattern}
+Set constant. @var{type-information} is the type of the constant, as it
+would appear after a symbol descriptor (@pxref{String Field}).
+@var{elements} is the number of elements in the set (does this means
+how many bits of @var{pattern} are actually used, which would be
+redundant with the type, or perhaps the number of bits set in
+@var{pattern}? I don't get it), @var{bits} is the number of bits in the
+constant (meaning it specifies the length of @var{pattern}, I think),
+and @var{pattern} is a hexadecimal representation of the set. AIX
+documentation refers to a limit of 32 bytes, but I see no reason why
+this limit should exist. This form could probably be used for arbitrary
+constants, not just sets; the only catch is that @var{pattern} should be
+understood to be target, not host, byte order and format.
+@end table
+
+The boolean, character, string, and set constants are not supported by
+GDB 4.9, but it ignores them. GDB 4.8 and earlier gave an error
+message and refused to read symbols from the file containing the
+constants.
+
+The above information is followed by @samp{;}.
+
+@node Variables
+@chapter Variables
+
+Different types of stabs describe the various ways that variables can be
+allocated: on the stack, globally, in registers, in common blocks,
+statically, or as arguments to a function.
+
+@menu
+* Stack Variables:: Variables allocated on the stack.
+* Global Variables:: Variables used by more than one source file.
+* Register Variables:: Variables in registers.
+* Common Blocks:: Variables statically allocated together.
+* Statics:: Variables local to one source file.
+* Based Variables:: Fortran pointer based variables.
+* Parameters:: Variables for arguments to functions.
+@end menu
+
+@node Stack Variables
+@section Automatic Variables Allocated on the Stack
+
+If a variable's scope is local to a function and its lifetime is only as
+long as that function executes (C calls such variables
+@dfn{automatic}), it can be allocated in a register (@pxref{Register
+Variables}) or on the stack.
+
+@findex N_LSYM
+Each variable allocated on the stack has a stab with the symbol
+descriptor omitted. Since type information should begin with a digit,
+@samp{-}, or @samp{(}, only those characters precluded from being used
+for symbol descriptors. However, the Acorn RISC machine (ARM) is said
+to get this wrong: it puts out a mere type definition here, without the
+preceding @samp{@var{type-number}=}. This is a bad idea; there is no
+guarantee that type descriptors are distinct from symbol descriptors.
+Stabs for stack variables use the @code{N_LSYM} stab type.
+
+The value of the stab is the offset of the variable within the
+local variables. On most machines this is an offset from the frame
+pointer and is negative. The location of the stab specifies which block
+it is defined in; see @ref{Block Structure}.
+
+For example, the following C code:
+
+@example
+int
+main ()
+@{
+ int x;
+@}
+@end example
+
+produces the following stabs:
+
+@example
+.stabs "main:F1",36,0,0,_main # @r{36 is N_FUN}
+.stabs "x:1",128,0,0,-12 # @r{128 is N_LSYM}
+.stabn 192,0,0,LBB2 # @r{192 is N_LBRAC}
+.stabn 224,0,0,LBE2 # @r{224 is N_RBRAC}
+@end example
+
+@xref{Procedures} for more information on the @code{N_FUN} stab, and
+@ref{Block Structure} for more information on the @code{N_LBRAC} and
+@code{N_RBRAC} stabs.
+
+@node Global Variables
+@section Global Variables
+
+@findex N_GSYM
+A variable whose scope is not specific to just one source file is
+represented by the @samp{G} symbol descriptor. These stabs use the
+@code{N_GSYM} stab type. The type information for the stab
+(@pxref{String Field}) gives the type of the variable.
+
+For example, the following source code:
+
+@example
+char g_foo = 'c';
+@end example
+
+@noindent
+yields the following assembly code:
+
+@example
+.stabs "g_foo:G2",32,0,0,0 # @r{32 is N_GSYM}
+ .global _g_foo
+ .data
+_g_foo:
+ .byte 99
+@end example
+
+The address of the variable represented by the @code{N_GSYM} is not
+contained in the @code{N_GSYM} stab. The debugger gets this information
+from the external symbol for the global variable. In the example above,
+the @code{.global _g_foo} and @code{_g_foo:} lines tell the assembler to
+produce an external symbol.
+
+@node Register Variables
+@section Register Variables
+
+@findex N_RSYM
+@c According to an old version of this manual, AIX uses C_RPSYM instead
+@c of C_RSYM. I am skeptical; this should be verified.
+Register variables have their own stab type, @code{N_RSYM}, and their
+own symbol descriptor, @samp{r}. The stab's value is the
+number of the register where the variable data will be stored.
+@c .stabs "name:type",N_RSYM,0,RegSize,RegNumber (Sun doc)
+
+AIX defines a separate symbol descriptor @samp{d} for floating point
+registers. This seems unnecessary; why not just just give floating
+point registers different register numbers? I have not verified whether
+the compiler actually uses @samp{d}.
+
+If the register is explicitly allocated to a global variable, but not
+initialized, as in:
+
+@example
+register int g_bar asm ("%g5");
+@end example
+
+@noindent
+then the stab may be emitted at the end of the object file, with
+the other bss symbols.
+
+@node Common Blocks
+@section Common Blocks
+
+A common block is a statically allocated section of memory which can be
+referred to by several source files. It may contain several variables.
+I believe Fortran is the only language with this feature.
+
+@findex N_BCOMM
+@findex N_ECOMM
+@findex C_BCOMM
+@findex C_ECOMM
+A @code{N_BCOMM} stab begins a common block and an @code{N_ECOMM} stab
+ends it. The only field that is significant in these two stabs is the
+string, which names a normal (non-debugging) symbol that gives the
+address of the common block. According to IBM documentation, only the
+@code{N_BCOMM} has the name of the common block (even though their
+compiler actually puts it both places).
+
+@findex N_ECOML
+@findex C_ECOML
+The stabs for the members of the common block are between the
+@code{N_BCOMM} and the @code{N_ECOMM}; the value of each stab is the
+offset within the common block of that variable. IBM uses the
+@code{C_ECOML} stab type, and there is a corresponding @code{N_ECOML}
+stab type, but Sun's Fortran compiler uses @code{N_GSYM} instead. The
+variables within a common block use the @samp{V} symbol descriptor (I
+believe this is true of all Fortran variables). Other stabs (at least
+type declarations using @code{C_DECL}) can also be between the
+@code{N_BCOMM} and the @code{N_ECOMM}.
+
+@node Statics
+@section Static Variables
+
+Initialized static variables are represented by the @samp{S} and
+@samp{V} symbol descriptors. @samp{S} means file scope static, and
+@samp{V} means procedure scope static.
+
+@c This is probably not worth mentioning; it is only true on the sparc
+@c for `double' variables which although declared const are actually in
+@c the data segment (the text segment can't guarantee 8 byte alignment).
+@c (although GCC
+@c 2.4.5 has a bug in that it uses @code{N_FUN}, so neither dbx nor GDB can
+@c find the variables)
+@findex N_STSYM
+@findex N_LCSYM
+@findex N_FUN, for variables
+@findex N_ROSYM
+In a.out files, @code{N_STSYM} means the data section, @code{N_FUN}
+means the text section, and @code{N_LCSYM} means the bss section. For
+those systems with a read-only data section separate from the text
+section (Solaris), @code{N_ROSYM} means the read-only data section.
+
+For example, the source lines:
+
+@example
+static const int var_const = 5;
+static int var_init = 2;
+static int var_noinit;
+@end example
+
+@noindent
+yield the following stabs:
+
+@example
+.stabs "var_const:S1",36,0,0,_var_const # @r{36 is N_FUN}
+@dots{}
+.stabs "var_init:S1",38,0,0,_var_init # @r{38 is N_STSYM}
+@dots{}
+.stabs "var_noinit:S1",40,0,0,_var_noinit # @r{40 is N_LCSYM}
+@end example
+
+In XCOFF files, each symbol has a section number, so the stab type
+need not indicate the section.
+
+In ECOFF files, the storage class is used to specify the section, so the
+stab type need not indicate the section.
+
+In ELF files, for the SunPRO compiler version 2.0.1, symbol descriptor
+@samp{S} means that the address is absolute (the linker relocates it)
+and symbol descriptor @samp{V} means that the address is relative to the
+start of the relevant section for that compilation unit. SunPRO has
+plans to have the linker stop relocating stabs; I suspect that their the
+debugger gets the address from the corresponding ELF (not stab) symbol.
+I'm not sure how to find which symbol of that name is the right one.
+The clean way to do all this would be to have a the value of a symbol
+descriptor @samp{S} symbol be an offset relative to the start of the
+file, just like everything else, but that introduces obvious
+compatibility problems. For more information on linker stab relocation,
+@xref{Stabs In ELF}.
+
+@node Based Variables
+@section Fortran Based Variables
+
+Fortran (at least, the Sun and SGI dialects of FORTRAN-77) has a feature
+which allows allocating arrays with @code{malloc}, but which avoids
+blurring the line between arrays and pointers the way that C does. In
+stabs such a variable uses the @samp{b} symbol descriptor.
+
+For example, the Fortran declarations
+
+@example
+real foo, foo10(10), foo10_5(10,5)
+pointer (foop, foo)
+pointer (foo10p, foo10)
+pointer (foo105p, foo10_5)
+@end example
+
+produce the stabs
+
+@example
+foo:b6
+foo10:bar3;1;10;6
+foo10_5:bar3;1;5;ar3;1;10;6
+@end example
+
+In this example, @code{real} is type 6 and type 3 is an integral type
+which is the type of the subscripts of the array (probably
+@code{integer}).
+
+The @samp{b} symbol descriptor is like @samp{V} in that it denotes a
+statically allocated symbol whose scope is local to a function; see
+@xref{Statics}. The value of the symbol, instead of being the address
+of the variable itself, is the address of a pointer to that variable.
+So in the above example, the value of the @code{foo} stab is the address
+of a pointer to a real, the value of the @code{foo10} stab is the
+address of a pointer to a 10-element array of reals, and the value of
+the @code{foo10_5} stab is the address of a pointer to a 5-element array
+of 10-element arrays of reals.
+
+@node Parameters
+@section Parameters
+
+Formal parameters to a function are represented by a stab (or sometimes
+two; see below) for each parameter. The stabs are in the order in which
+the debugger should print the parameters (i.e., the order in which the
+parameters are declared in the source file). The exact form of the stab
+depends on how the parameter is being passed.
+
+@findex N_PSYM
+Parameters passed on the stack use the symbol descriptor @samp{p} and
+the @code{N_PSYM} symbol type. The value of the symbol is an offset
+used to locate the parameter on the stack; its exact meaning is
+machine-dependent, but on most machines it is an offset from the frame
+pointer.
+
+As a simple example, the code:
+
+@example
+main (argc, argv)
+ int argc;
+ char **argv;
+@end example
+
+produces the stabs:
+
+@example
+.stabs "main:F1",36,0,0,_main # @r{36 is N_FUN}
+.stabs "argc:p1",160,0,0,68 # @r{160 is N_PSYM}
+.stabs "argv:p20=*21=*2",160,0,0,72
+@end example
+
+The type definition of @code{argv} is interesting because it contains
+several type definitions. Type 21 is pointer to type 2 (char) and
+@code{argv} (type 20) is pointer to type 21.
+
+@c FIXME: figure out what these mean and describe them coherently.
+The following symbol descriptors are also said to go with @code{N_PSYM}.
+The value of the symbol is said to be an offset from the argument
+pointer (I'm not sure whether this is true or not).
+
+@example
+pP (<<??>>)
+pF Fortran function parameter
+X (function result variable)
+@end example
+
+@menu
+* Register Parameters::
+* Local Variable Parameters::
+* Reference Parameters::
+* Conformant Arrays::
+@end menu
+
+@node Register Parameters
+@subsection Passing Parameters in Registers
+
+If the parameter is passed in a register, then traditionally there are
+two symbols for each argument:
+
+@example
+.stabs "arg:p1" . . . ; N_PSYM
+.stabs "arg:r1" . . . ; N_RSYM
+@end example
+
+Debuggers use the second one to find the value, and the first one to
+know that it is an argument.
+
+@findex C_RPSYM
+@findex N_RSYM, for parameters
+Because that approach is kind of ugly, some compilers use symbol
+descriptor @samp{P} or @samp{R} to indicate an argument which is in a
+register. Symbol type @code{C_RPSYM} is used with @samp{R} and
+@code{N_RSYM} is used with @samp{P}. The symbol's value is
+the register number. @samp{P} and @samp{R} mean the same thing; the
+difference is that @samp{P} is a GNU invention and @samp{R} is an IBM
+(XCOFF) invention. As of version 4.9, GDB should handle either one.
+
+There is at least one case where GCC uses a @samp{p} and @samp{r} pair
+rather than @samp{P}; this is where the argument is passed in the
+argument list and then loaded into a register.
+
+According to the AIX documentation, symbol descriptor @samp{D} is for a
+parameter passed in a floating point register. This seems
+unnecessary---why not just use @samp{R} with a register number which
+indicates that it's a floating point register? I haven't verified
+whether the system actually does what the documentation indicates.
+
+@c FIXME: On the hppa this is for any type > 8 bytes, I think, and not
+@c for small structures (investigate).
+On the sparc and hppa, for a @samp{P} symbol whose type is a structure
+or union, the register contains the address of the structure. On the
+sparc, this is also true of a @samp{p} and @samp{r} pair (using Sun
+@code{cc}) or a @samp{p} symbol. However, if a (small) structure is
+really in a register, @samp{r} is used. And, to top it all off, on the
+hppa it might be a structure which was passed on the stack and loaded
+into a register and for which there is a @samp{p} and @samp{r} pair! I
+believe that symbol descriptor @samp{i} is supposed to deal with this
+case (it is said to mean "value parameter by reference, indirect
+access"; I don't know the source for this information), but I don't know
+details or what compilers or debuggers use it, if any (not GDB or GCC).
+It is not clear to me whether this case needs to be dealt with
+differently than parameters passed by reference (@pxref{Reference Parameters}).
+
+@node Local Variable Parameters
+@subsection Storing Parameters as Local Variables
+
+There is a case similar to an argument in a register, which is an
+argument that is actually stored as a local variable. Sometimes this
+happens when the argument was passed in a register and then the compiler
+stores it as a local variable. If possible, the compiler should claim
+that it's in a register, but this isn't always done.
+
+@findex N_LSYM, for parameter
+Some compilers use the pair of symbols approach described above
+(@samp{@var{arg}:p} followed by @samp{@var{arg}:}); this includes GCC1
+(not GCC2) on the sparc when passing a small structure and GCC2
+(sometimes) when the argument type is @code{float} and it is passed as a
+@code{double} and converted to @code{float} by the prologue (in the
+latter case the type of the @samp{@var{arg}:p} symbol is @code{double}
+and the type of the @samp{@var{arg}:} symbol is @code{float}).
+
+GCC, at least on the 960, has another solution to the same problem. It
+uses a single @samp{p} symbol descriptor for an argument which is stored
+as a local variable but uses @code{N_LSYM} instead of @code{N_PSYM}. In
+this case, the value of the symbol is an offset relative to the local
+variables for that function, not relative to the arguments; on some
+machines those are the same thing, but not on all.
+
+@c This is mostly just background info; the part that logically belongs
+@c here is the last sentence.
+On the VAX or on other machines in which the calling convention includes
+the number of words of arguments actually passed, the debugger (GDB at
+least) uses the parameter symbols to keep track of whether it needs to
+print nameless arguments in addition to the formal parameters which it
+has printed because each one has a stab. For example, in
+
+@example
+extern int fprintf (FILE *stream, char *format, @dots{});
+@dots{}
+fprintf (stdout, "%d\n", x);
+@end example
+
+there are stabs for @code{stream} and @code{format}. On most machines,
+the debugger can only print those two arguments (because it has no way
+of knowing that additional arguments were passed), but on the VAX or
+other machines with a calling convention which indicates the number of
+words of arguments, the debugger can print all three arguments. To do
+so, the parameter symbol (symbol descriptor @samp{p}) (not necessarily
+@samp{r} or symbol descriptor omitted symbols) needs to contain the
+actual type as passed (for example, @code{double} not @code{float} if it
+is passed as a double and converted to a float).
+
+@node Reference Parameters
+@subsection Passing Parameters by Reference
+
+If the parameter is passed by reference (e.g., Pascal @code{VAR}
+parameters), then the symbol descriptor is @samp{v} if it is in the
+argument list, or @samp{a} if it in a register. Other than the fact
+that these contain the address of the parameter rather than the
+parameter itself, they are identical to @samp{p} and @samp{R},
+respectively. I believe @samp{a} is an AIX invention; @samp{v} is
+supported by all stabs-using systems as far as I know.
+
+@node Conformant Arrays
+@subsection Passing Conformant Array Parameters
+
+@c Is this paragraph correct? It is based on piecing together patchy
+@c information and some guesswork
+Conformant arrays are a feature of Modula-2, and perhaps other
+languages, in which the size of an array parameter is not known to the
+called function until run-time. Such parameters have two stabs: a
+@samp{x} for the array itself, and a @samp{C}, which represents the size
+of the array. The value of the @samp{x} stab is the offset in the
+argument list where the address of the array is stored (it this right?
+it is a guess); the value of the @samp{C} stab is the offset in the
+argument list where the size of the array (in elements? in bytes?) is
+stored.
+
+@node Types
+@chapter Defining Types
+
+The examples so far have described types as references to previously
+defined types, or defined in terms of subranges of or pointers to
+previously defined types. This chapter describes the other type
+descriptors that may follow the @samp{=} in a type definition.
+
+@menu
+* Builtin Types:: Integers, floating point, void, etc.
+* Miscellaneous Types:: Pointers, sets, files, etc.
+* Cross-References:: Referring to a type not yet defined.
+* Subranges:: A type with a specific range.
+* Arrays:: An aggregate type of same-typed elements.
+* Strings:: Like an array but also has a length.
+* Enumerations:: Like an integer but the values have names.
+* Structures:: An aggregate type of different-typed elements.
+* Typedefs:: Giving a type a name.
+* Unions:: Different types sharing storage.
+* Function Types::
+@end menu
+
+@node Builtin Types
+@section Builtin Types
+
+Certain types are built in (@code{int}, @code{short}, @code{void},
+@code{float}, etc.); the debugger recognizes these types and knows how
+to handle them. Thus, don't be surprised if some of the following ways
+of specifying builtin types do not specify everything that a debugger
+would need to know about the type---in some cases they merely specify
+enough information to distinguish the type from other types.
+
+The traditional way to define builtin types is convolunted, so new ways
+have been invented to describe them. Sun's @code{acc} uses special
+builtin type descriptors (@samp{b} and @samp{R}), and IBM uses negative
+type numbers. GDB accepts all three ways, as of version 4.8; dbx just
+accepts the traditional builtin types and perhaps one of the other two
+formats. The following sections describe each of these formats.
+
+@menu
+* Traditional Builtin Types:: Put on your seatbelts and prepare for kludgery
+* Builtin Type Descriptors:: Builtin types with special type descriptors
+* Negative Type Numbers:: Builtin types using negative type numbers
+@end menu
+
+@node Traditional Builtin Types
+@subsection Traditional Builtin Types
+
+This is the traditional, convoluted method for defining builtin types.
+There are several classes of such type definitions: integer, floating
+point, and @code{void}.
+
+@menu
+* Traditional Integer Types::
+* Traditional Other Types::
+@end menu
+
+@node Traditional Integer Types
+@subsubsection Traditional Integer Types
+
+Often types are defined as subranges of themselves. If the bounding values
+fit within an @code{int}, then they are given normally. For example:
+
+@example
+.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0 # @r{128 is N_LSYM}
+.stabs "char:t2=r2;0;127;",128,0,0,0
+@end example
+
+Builtin types can also be described as subranges of @code{int}:
+
+@example
+.stabs "unsigned short:t6=r1;0;65535;",128,0,0,0
+@end example
+
+If the lower bound of a subrange is 0 and the upper bound is -1,
+the type is an unsigned integral type whose bounds are too
+big to describe in an @code{int}. Traditionally this is only used for
+@code{unsigned int} and @code{unsigned long}:
+
+@example
+.stabs "unsigned int:t4=r1;0;-1;",128,0,0,0
+@end example
+
+For larger types, GCC 2.4.5 puts out bounds in octal, with one or more
+leading zeroes. In this case a negative bound consists of a number
+which is a 1 bit (for the sign bit) followed by a 0 bit for each bit in
+the number (except the sign bit), and a positive bound is one which is a
+1 bit for each bit in the number (except possibly the sign bit). All
+known versions of dbx and GDB version 4 accept this (at least in the
+sense of not refusing to process the file), but GDB 3.5 refuses to read
+the whole file containing such symbols. So GCC 2.3.3 did not output the
+proper size for these types. As an example of octal bounds, the string
+fields of the stabs for 64 bit integer types look like:
+
+@c .stabs directives, etc., omitted to make it fit on the page.
+@example
+long int:t3=r1;001000000000000000000000;000777777777777777777777;
+long unsigned int:t5=r1;000000000000000000000000;001777777777777777777777;
+@end example
+
+If the lower bound of a subrange is 0 and the upper bound is negative,
+the type is an unsigned integral type whose size in bytes is the
+absolute value of the upper bound. I believe this is a Convex
+convention for @code{unsigned long long}.
+
+If the lower bound of a subrange is negative and the upper bound is 0,
+the type is a signed integral type whose size in bytes is
+the absolute value of the lower bound. I believe this is a Convex
+convention for @code{long long}. To distinguish this from a legitimate
+subrange, the type should be a subrange of itself. I'm not sure whether
+this is the case for Convex.
+
+@node Traditional Other Types
+@subsubsection Traditional Other Types
+
+If the upper bound of a subrange is 0 and the lower bound is positive,
+the type is a floating point type, and the lower bound of the subrange
+indicates the number of bytes in the type:
+
+@example
+.stabs "float:t12=r1;4;0;",128,0,0,0
+.stabs "double:t13=r1;8;0;",128,0,0,0
+@end example
+
+However, GCC writes @code{long double} the same way it writes
+@code{double}, so there is no way to distinguish.
+
+@example
+.stabs "long double:t14=r1;8;0;",128,0,0,0
+@end example
+
+Complex types are defined the same way as floating-point types; there is
+no way to distinguish a single-precision complex from a double-precision
+floating-point type.
+
+The C @code{void} type is defined as itself:
+
+@example
+.stabs "void:t15=15",128,0,0,0
+@end example
+
+I'm not sure how a boolean type is represented.
+
+@node Builtin Type Descriptors
+@subsection Defining Builtin Types Using Builtin Type Descriptors
+
+This is the method used by Sun's @code{acc} for defining builtin types.
+These are the type descriptors to define builtin types:
+
+@table @code
+@c FIXME: clean up description of width and offset, once we figure out
+@c what they mean
+@item b @var{signed} @var{char-flag} @var{width} ; @var{offset} ; @var{nbits} ;
+Define an integral type. @var{signed} is @samp{u} for unsigned or
+@samp{s} for signed. @var{char-flag} is @samp{c} which indicates this
+is a character type, or is omitted. I assume this is to distinguish an
+integral type from a character type of the same size, for example it
+might make sense to set it for the C type @code{wchar_t} so the debugger
+can print such variables differently (Solaris does not do this). Sun
+sets it on the C types @code{signed char} and @code{unsigned char} which
+arguably is wrong. @var{width} and @var{offset} appear to be for small
+objects stored in larger ones, for example a @code{short} in an
+@code{int} register. @var{width} is normally the number of bytes in the
+type. @var{offset} seems to always be zero. @var{nbits} is the number
+of bits in the type.
+
+Note that type descriptor @samp{b} used for builtin types conflicts with
+its use for Pascal space types (@pxref{Miscellaneous Types}); they can
+be distinguished because the character following the type descriptor
+will be a digit, @samp{(}, or @samp{-} for a Pascal space type, or
+@samp{u} or @samp{s} for a builtin type.
+
+@item w
+Documented by AIX to define a wide character type, but their compiler
+actually uses negative type numbers (@pxref{Negative Type Numbers}).
+
+@item R @var{fp-type} ; @var{bytes} ;
+Define a floating point type. @var{fp-type} has one of the following values:
+
+@table @code
+@item 1 (NF_SINGLE)
+IEEE 32-bit (single precision) floating point format.
+
+@item 2 (NF_DOUBLE)
+IEEE 64-bit (double precision) floating point format.
+
+@item 3 (NF_COMPLEX)
+@item 4 (NF_COMPLEX16)
+@item 5 (NF_COMPLEX32)
+@c "GDB source" really means @file{include/aout/stab_gnu.h}, but trying
+@c to put that here got an overfull hbox.
+These are for complex numbers. A comment in the GDB source describes
+them as Fortran @code{complex}, @code{double complex}, and
+@code{complex*16}, respectively, but what does that mean? (i.e., Single
+precision? Double precison?).
+
+@item 6 (NF_LDOUBLE)
+Long double. This should probably only be used for Sun format
+@code{long double}, and new codes should be used for other floating
+point formats (@code{NF_DOUBLE} can be used if a @code{long double} is
+really just an IEEE double, of course).
+@end table
+
+@var{bytes} is the number of bytes occupied by the type. This allows a
+debugger to perform some operations with the type even if it doesn't
+understand @var{fp-type}.
+
+@item g @var{type-information} ; @var{nbits}
+Documented by AIX to define a floating type, but their compiler actually
+uses negative type numbers (@pxref{Negative Type Numbers}).
+
+@item c @var{type-information} ; @var{nbits}
+Documented by AIX to define a complex type, but their compiler actually
+uses negative type numbers (@pxref{Negative Type Numbers}).
+@end table
+
+The C @code{void} type is defined as a signed integral type 0 bits long:
+@example
+.stabs "void:t19=bs0;0;0",128,0,0,0
+@end example
+The Solaris compiler seems to omit the trailing semicolon in this case.
+Getting sloppy in this way is not a swift move because if a type is
+embedded in a more complex expression it is necessary to be able to tell
+where it ends.
+
+I'm not sure how a boolean type is represented.
+
+@node Negative Type Numbers
+@subsection Negative Type Numbers
+
+This is the method used in XCOFF for defining builtin types.
+Since the debugger knows about the builtin types anyway, the idea of
+negative type numbers is simply to give a special type number which
+indicates the builtin type. There is no stab defining these types.
+
+There are several subtle issues with negative type numbers.
+
+One is the size of the type. A builtin type (for example the C types
+@code{int} or @code{long}) might have different sizes depending on
+compiler options, the target architecture, the ABI, etc. This issue
+doesn't come up for IBM tools since (so far) they just target the
+RS/6000; the sizes indicated below for each size are what the IBM
+RS/6000 tools use. To deal with differing sizes, either define separate
+negative type numbers for each size (which works but requires changing
+the debugger, and, unless you get both AIX dbx and GDB to accept the
+change, introduces an incompatibility), or use a type attribute
+(@pxref{String Field}) to define a new type with the appropriate size
+(which merely requires a debugger which understands type attributes,
+like AIX dbx). For example,
+
+@example
+.stabs "boolean:t10=@@s8;-16",128,0,0,0
+@end example
+
+defines an 8-bit boolean type, and
+
+@example
+.stabs "boolean:t10=@@s64;-16",128,0,0,0
+@end example
+
+defines a 64-bit boolean type.
+
+A similar issue is the format of the type. This comes up most often for
+floating-point types, which could have various formats (particularly
+extended doubles, which vary quite a bit even among IEEE systems).
+Again, it is best to define a new negative type number for each
+different format; changing the format based on the target system has
+various problems. One such problem is that the Alpha has both VAX and
+IEEE floating types. One can easily imagine one library using the VAX
+types and another library in the same executable using the IEEE types.
+Another example is that the interpretation of whether a boolean is true
+or false can be based on the least significant bit, most significant
+bit, whether it is zero, etc., and different compilers (or different
+options to the same compiler) might provide different kinds of boolean.
+
+The last major issue is the names of the types. The name of a given
+type depends @emph{only} on the negative type number given; these do not
+vary depending on the language, the target system, or anything else.
+One can always define separate type numbers---in the following list you
+will see for example separate @code{int} and @code{integer*4} types
+which are identical except for the name. But compatibility can be
+maintained by not inventing new negative type numbers and instead just
+defining a new type with a new name. For example:
+
+@example
+.stabs "CARDINAL:t10=-8",128,0,0,0
+@end example
+
+Here is the list of negative type numbers. The phrase @dfn{integral
+type} is used to mean twos-complement (I strongly suspect that all
+machines which use stabs use twos-complement; most machines use
+twos-complement these days).
+
+@table @code
+@item -1
+@code{int}, 32 bit signed integral type.
+
+@item -2
+@code{char}, 8 bit type holding a character. Both GDB and dbx on AIX
+treat this as signed. GCC uses this type whether @code{char} is signed
+or not, which seems like a bad idea. The AIX compiler (@code{xlc}) seems to
+avoid this type; it uses -5 instead for @code{char}.
+
+@item -3
+@code{short}, 16 bit signed integral type.
+
+@item -4
+@code{long}, 32 bit signed integral type.
+
+@item -5
+@code{unsigned char}, 8 bit unsigned integral type.
+
+@item -6
+@code{signed char}, 8 bit signed integral type.
+
+@item -7
+@code{unsigned short}, 16 bit unsigned integral type.
+
+@item -8
+@code{unsigned int}, 32 bit unsigned integral type.
+
+@item -9
+@code{unsigned}, 32 bit unsigned integral type.
+
+@item -10
+@code{unsigned long}, 32 bit unsigned integral type.
+
+@item -11
+@code{void}, type indicating the lack of a value.
+
+@item -12
+@code{float}, IEEE single precision.
+
+@item -13
+@code{double}, IEEE double precision.
+
+@item -14
+@code{long double}, IEEE double precision. The compiler claims the size
+will increase in a future release, and for binary compatibility you have
+to avoid using @code{long double}. I hope when they increase it they
+use a new negative type number.
+
+@item -15
+@code{integer}. 32 bit signed integral type.
+
+@item -16
+@code{boolean}. 32 bit type. How is the truth value encoded? Is it
+the least significant bit or is it a question of whether the whole value
+is zero or non-zero?
+
+@item -17
+@code{short real}. IEEE single precision.
+
+@item -18
+@code{real}. IEEE double precision.
+
+@item -19
+@code{stringptr}. @xref{Strings}.
+
+@item -20
+@code{character}, 8 bit unsigned character type.
+
+@item -21
+@code{logical*1}, 8 bit type. This Fortran type has a split
+personality in that it is used for boolean variables, but can also be
+used for unsigned integers. 0 is false, 1 is true, and other values are
+non-boolean.
+
+@item -22
+@code{logical*2}, 16 bit type. This Fortran type has a split
+personality in that it is used for boolean variables, but can also be
+used for unsigned integers. 0 is false, 1 is true, and other values are
+non-boolean.
+
+@item -23
+@code{logical*4}, 32 bit type. This Fortran type has a split
+personality in that it is used for boolean variables, but can also be
+used for unsigned integers. 0 is false, 1 is true, and other values are
+non-boolean.
+
+@item -24
+@code{logical}, 32 bit type. This Fortran type has a split
+personality in that it is used for boolean variables, but can also be
+used for unsigned integers. 0 is false, 1 is true, and other values are
+non-boolean.
+
+@item -25
+@code{complex}. A complex type consisting of two IEEE single-precision
+floating point values.
+
+@item -26
+@code{complex}. A complex type consisting of two IEEE double-precision
+floating point values.
+
+@item -27
+@code{integer*1}, 8 bit signed integral type.
+
+@item -28
+@code{integer*2}, 16 bit signed integral type.
+
+@item -29
+@code{integer*4}, 32 bit signed integral type.
+
+@item -30
+@code{wchar}. Wide character, 16 bits wide, unsigned (what format?
+Unicode?).
+@end table
+
+@node Miscellaneous Types
+@section Miscellaneous Types
+
+@table @code
+@item b @var{type-information} ; @var{bytes}
+Pascal space type. This is documented by IBM; what does it mean?
+
+This use of the @samp{b} type descriptor can be distinguished
+from its use for builtin integral types (@pxref{Builtin Type
+Descriptors}) because the character following the type descriptor is
+always a digit, @samp{(}, or @samp{-}.
+
+@item B @var{type-information}
+A volatile-qualified version of @var{type-information}. This is
+a Sun extension. References and stores to a variable with a
+volatile-qualified type must not be optimized or cached; they
+must occur as the user specifies them.
+
+@item d @var{type-information}
+File of type @var{type-information}. As far as I know this is only used
+by Pascal.
+
+@item k @var{type-information}
+A const-qualified version of @var{type-information}. This is a Sun
+extension. A variable with a const-qualified type cannot be modified.
+
+@item M @var{type-information} ; @var{length}
+Multiple instance type. The type seems to composed of @var{length}
+repetitions of @var{type-information}, for example @code{character*3} is
+represented by @samp{M-2;3}, where @samp{-2} is a reference to a
+character type (@pxref{Negative Type Numbers}). I'm not sure how this
+differs from an array. This appears to be a Fortran feature.
+@var{length} is a bound, like those in range types; see @ref{Subranges}.
+
+@item S @var{type-information}
+Pascal set type. @var{type-information} must be a small type such as an
+enumeration or a subrange, and the type is a bitmask whose length is
+specified by the number of elements in @var{type-information}.
+
+@item * @var{type-information}
+Pointer to @var{type-information}.
+@end table
+
+@node Cross-References
+@section Cross-References to Other Types
+
+A type can be used before it is defined; one common way to deal with
+that situation is just to use a type reference to a type which has not
+yet been defined.
+
+Another way is with the @samp{x} type descriptor, which is followed by
+@samp{s} for a structure tag, @samp{u} for a union tag, or @samp{e} for
+a enumerator tag, followed by the name of the tag, followed by @samp{:}.
+For example, the following C declarations:
+
+@example
+struct foo;
+struct foo *bar;
+@end example
+
+@noindent
+produce:
+
+@example
+.stabs "bar:G16=*17=xsfoo:",32,0,0,0
+@end example
+
+Not all debuggers support the @samp{x} type descriptor, so on some
+machines GCC does not use it. I believe that for the above example it
+would just emit a reference to type 17 and never define it, but I
+haven't verified that.
+
+Modula-2 imported types, at least on AIX, use the @samp{i} type
+descriptor, which is followed by the name of the module from which the
+type is imported, followed by @samp{:}, followed by the name of the
+type. There is then optionally a comma followed by type information for
+the type. This differs from merely naming the type (@pxref{Typedefs}) in
+that it identifies the module; I don't understand whether the name of
+the type given here is always just the same as the name we are giving
+it, or whether this type descriptor is used with a nameless stab
+(@pxref{String Field}), or what. The symbol ends with @samp{;}.
+
+@node Subranges
+@section Subrange Types
+
+The @samp{r} type descriptor defines a type as a subrange of another
+type. It is followed by type information for the type of which it is a
+subrange, a semicolon, an integral lower bound, a semicolon, an
+integral upper bound, and a semicolon. The AIX documentation does not
+specify the trailing semicolon, in an effort to specify array indexes
+more cleanly, but a subrange which is not an array index has always
+included a trailing semicolon (@pxref{Arrays}).
+
+Instead of an integer, either bound can be one of the following:
+
+@table @code
+@item A @var{offset}
+The bound is passed by reference on the stack at offset @var{offset}
+from the argument list. @xref{Parameters}, for more information on such
+offsets.
+
+@item T @var{offset}
+The bound is passed by value on the stack at offset @var{offset} from
+the argument list.
+
+@item a @var{register-number}
+The bound is pased by reference in register number
+@var{register-number}.
+
+@item t @var{register-number}
+The bound is passed by value in register number @var{register-number}.
+
+@item J
+There is no bound.
+@end table
+
+Subranges are also used for builtin types; see @ref{Traditional Builtin Types}.
+
+@node Arrays
+@section Array Types
+
+Arrays use the @samp{a} type descriptor. Following the type descriptor
+is the type of the index and the type of the array elements. If the
+index type is a range type, it ends in a semicolon; otherwise
+(for example, if it is a type reference), there does not
+appear to be any way to tell where the types are separated. In an
+effort to clean up this mess, IBM documents the two types as being
+separated by a semicolon, and a range type as not ending in a semicolon
+(but this is not right for range types which are not array indexes,
+@pxref{Subranges}). I think probably the best solution is to specify
+that a semicolon ends a range type, and that the index type and element
+type of an array are separated by a semicolon, but that if the index
+type is a range type, the extra semicolon can be omitted. GDB (at least
+through version 4.9) doesn't support any kind of index type other than a
+range anyway; I'm not sure about dbx.
+
+It is well established, and widely used, that the type of the index,
+unlike most types found in the stabs, is merely a type definition, not
+type information (@pxref{String Field}) (that is, it need not start with
+@samp{@var{type-number}=} if it is defining a new type). According to a
+comment in GDB, this is also true of the type of the array elements; it
+gives @samp{ar1;1;10;ar1;1;10;4} as a legitimate way to express a two
+dimensional array. According to AIX documentation, the element type
+must be type information. GDB accepts either.
+
+The type of the index is often a range type, expressed as the type
+descriptor @samp{r} and some parameters. It defines the size of the
+array. In the example below, the range @samp{r1;0;2;} defines an index
+type which is a subrange of type 1 (integer), with a lower bound of 0
+and an upper bound of 2. This defines the valid range of subscripts of
+a three-element C array.
+
+For example, the definition:
+
+@example
+char char_vec[3] = @{'a','b','c'@};
+@end example
+
+@noindent
+produces the output:
+
+@example
+.stabs "char_vec:G19=ar1;0;2;2",32,0,0,0
+ .global _char_vec
+ .align 4
+_char_vec:
+ .byte 97
+ .byte 98
+ .byte 99
+@end example
+
+If an array is @dfn{packed}, the elements are spaced more
+closely than normal, saving memory at the expense of speed. For
+example, an array of 3-byte objects might, if unpacked, have each
+element aligned on a 4-byte boundary, but if packed, have no padding.
+One way to specify that something is packed is with type attributes
+(@pxref{String Field}). In the case of arrays, another is to use the
+@samp{P} type descriptor instead of @samp{a}. Other than specifying a
+packed array, @samp{P} is identical to @samp{a}.
+
+@c FIXME-what is it? A pointer?
+An open array is represented by the @samp{A} type descriptor followed by
+type information specifying the type of the array elements.
+
+@c FIXME: what is the format of this type? A pointer to a vector of pointers?
+An N-dimensional dynamic array is represented by
+
+@example
+D @var{dimensions} ; @var{type-information}
+@end example
+
+@c Does dimensions really have this meaning? The AIX documentation
+@c doesn't say.
+@var{dimensions} is the number of dimensions; @var{type-information}
+specifies the type of the array elements.
+
+@c FIXME: what is the format of this type? A pointer to some offsets in
+@c another array?
+A subarray of an N-dimensional array is represented by
+
+@example
+E @var{dimensions} ; @var{type-information}
+@end example
+
+@c Does dimensions really have this meaning? The AIX documentation
+@c doesn't say.
+@var{dimensions} is the number of dimensions; @var{type-information}
+specifies the type of the array elements.
+
+@node Strings
+@section Strings
+
+Some languages, like C or the original Pascal, do not have string types,
+they just have related things like arrays of characters. But most
+Pascals and various other languages have string types, which are
+indicated as follows:
+
+@table @code
+@item n @var{type-information} ; @var{bytes}
+@var{bytes} is the maximum length. I'm not sure what
+@var{type-information} is; I suspect that it means that this is a string
+of @var{type-information} (thus allowing a string of integers, a string
+of wide characters, etc., as well as a string of characters). Not sure
+what the format of this type is. This is an AIX feature.
+
+@item z @var{type-information} ; @var{bytes}
+Just like @samp{n} except that this is a gstring, not an ordinary
+string. I don't know the difference.
+
+@item N
+Pascal Stringptr. What is this? This is an AIX feature.
+@end table
+
+@node Enumerations
+@section Enumerations
+
+Enumerations are defined with the @samp{e} type descriptor.
+
+@c FIXME: Where does this information properly go? Perhaps it is
+@c redundant with something we already explain.
+The source line below declares an enumeration type at file scope.
+The type definition is located after the @code{N_RBRAC} that marks the end of
+the previous procedure's block scope, and before the @code{N_FUN} that marks
+the beginning of the next procedure's block scope. Therefore it does not
+describe a block local symbol, but a file local one.
+
+The source line:
+
+@example
+enum e_places @{first,second=3,last@};
+@end example
+
+@noindent
+generates the following stab:
+
+@example
+.stabs "e_places:T22=efirst:0,second:3,last:4,;",128,0,0,0
+@end example
+
+The symbol descriptor (@samp{T}) says that the stab describes a
+structure, enumeration, or union tag. The type descriptor @samp{e},
+following the @samp{22=} of the type definition narrows it down to an
+enumeration type. Following the @samp{e} is a list of the elements of
+the enumeration. The format is @samp{@var{name}:@var{value},}. The
+list of elements ends with @samp{;}.
+
+There is no standard way to specify the size of an enumeration type; it
+is determined by the architecture (normally all enumerations types are
+32 bits). There should be a way to specify an enumeration type of
+another size; type attributes would be one way to do this. @xref{Stabs
+Format}.
+
+@node Structures
+@section Structures
+
+The encoding of structures in stabs can be shown with an example.
+
+The following source code declares a structure tag and defines an
+instance of the structure in global scope. Then a @code{typedef} equates the
+structure tag with a new type. Seperate stabs are generated for the
+structure tag, the structure @code{typedef}, and the structure instance. The
+stabs for the tag and the @code{typedef} are emited when the definitions are
+encountered. Since the structure elements are not initialized, the
+stab and code for the structure variable itself is located at the end
+of the program in the bss section.
+
+@example
+struct s_tag @{
+ int s_int;
+ float s_float;
+ char s_char_vec[8];
+ struct s_tag* s_next;
+@} g_an_s;
+
+typedef struct s_tag s_typedef;
+@end example
+
+The structure tag has an @code{N_LSYM} stab type because, like the
+enumeration, the symbol has file scope. Like the enumeration, the
+symbol descriptor is @samp{T}, for enumeration, structure, or tag type.
+The type descriptor @samp{s} following the @samp{16=} of the type
+definition narrows the symbol type to structure.
+
+Following the @samp{s} type descriptor is the number of bytes the
+structure occupies, followed by a description of each structure element.
+The structure element descriptions are of the form @var{name:type, bit
+offset from the start of the struct, number of bits in the element}.
+
+@c FIXME: phony line break. Can probably be fixed by using an example
+@c with fewer fields.
+@example
+# @r{128 is N_LSYM}
+.stabs "s_tag:T16=s20s_int:1,0,32;s_float:12,32,32;
+ s_char_vec:17=ar1;0;7;2,64,64;s_next:18=*16,128,32;;",128,0,0,0
+@end example
+
+In this example, the first two structure elements are previously defined
+types. For these, the type following the @samp{@var{name}:} part of the
+element description is a simple type reference. The other two structure
+elements are new types. In this case there is a type definition
+embedded after the @samp{@var{name}:}. The type definition for the
+array element looks just like a type definition for a standalone array.
+The @code{s_next} field is a pointer to the same kind of structure that
+the field is an element of. So the definition of structure type 16
+contains a type definition for an element which is a pointer to type 16.
+
+@node Typedefs
+@section Giving a Type a Name
+
+To give a type a name, use the @samp{t} symbol descriptor. The type
+is specified by the type information (@pxref{String Field}) for the stab.
+For example,
+
+@example
+.stabs "s_typedef:t16",128,0,0,0 # @r{128 is N_LSYM}
+@end example
+
+specifies that @code{s_typedef} refers to type number 16. Such stabs
+have symbol type @code{N_LSYM} (or @code{C_DECL} for XCOFF).
+
+If you are specifying the tag name for a structure, union, or
+enumeration, use the @samp{T} symbol descriptor instead. I believe C is
+the only language with this feature.
+
+If the type is an opaque type (I believe this is a Modula-2 feature),
+AIX provides a type descriptor to specify it. The type descriptor is
+@samp{o} and is followed by a name. I don't know what the name
+means---is it always the same as the name of the type, or is this type
+descriptor used with a nameless stab (@pxref{String Field})? There
+optionally follows a comma followed by type information which defines
+the type of this type. If omitted, a semicolon is used in place of the
+comma and the type information, and the type is much like a generic
+pointer type---it has a known size but little else about it is
+specified.
+
+@node Unions
+@section Unions
+
+@example
+union u_tag @{
+ int u_int;
+ float u_float;
+ char* u_char;
+@} an_u;
+@end example
+
+This code generates a stab for a union tag and a stab for a union
+variable. Both use the @code{N_LSYM} stab type. If a union variable is
+scoped locally to the procedure in which it is defined, its stab is
+located immediately preceding the @code{N_LBRAC} for the procedure's block
+start.
+
+The stab for the union tag, however, is located preceding the code for
+the procedure in which it is defined. The stab type is @code{N_LSYM}. This
+would seem to imply that the union type is file scope, like the struct
+type @code{s_tag}. This is not true. The contents and position of the stab
+for @code{u_type} do not convey any infomation about its procedure local
+scope.
+
+@c FIXME: phony line break. Can probably be fixed by using an example
+@c with fewer fields.
+@smallexample
+# @r{128 is N_LSYM}
+.stabs "u_tag:T23=u4u_int:1,0,32;u_float:12,0,32;u_char:21,0,32;;",
+ 128,0,0,0
+@end smallexample
+
+The symbol descriptor @samp{T}, following the @samp{name:} means that
+the stab describes an enumeration, structure, or union tag. The type
+descriptor @samp{u}, following the @samp{23=} of the type definition,
+narrows it down to a union type definition. Following the @samp{u} is
+the number of bytes in the union. After that is a list of union element
+descriptions. Their format is @var{name:type, bit offset into the
+union, number of bytes for the element;}.
+
+The stab for the union variable is:
+
+@example
+.stabs "an_u:23",128,0,0,-20 # @r{128 is N_LSYM}
+@end example
+
+@samp{-20} specifies where the variable is stored (@pxref{Stack
+Variables}).
+
+@node Function Types
+@section Function Types
+
+Various types can be defined for function variables. These types are
+not used in defining functions (@pxref{Procedures}); they are used for
+things like pointers to functions.
+
+The simple, traditional, type is type descriptor @samp{f} is followed by
+type information for the return type of the function, followed by a
+semicolon.
+
+This does not deal with functions for which the number and types of the
+parameters are part of the type, as in Modula-2 or ANSI C. AIX provides
+extensions to specify these, using the @samp{f}, @samp{F}, @samp{p}, and
+@samp{R} type descriptors.
+
+First comes the type descriptor. If it is @samp{f} or @samp{F}, this
+type involves a function rather than a procedure, and the type
+information for the return type of the function follows, followed by a
+comma. Then comes the number of parameters to the function and a
+semicolon. Then, for each parameter, there is the name of the parameter
+followed by a colon (this is only present for type descriptors @samp{R}
+and @samp{F} which represent Pascal function or procedure parameters),
+type information for the parameter, a comma, 0 if passed by reference or
+1 if passed by value, and a semicolon. The type definition ends with a
+semicolon.
+
+For example, this variable definition:
+
+@example
+int (*g_pf)();
+@end example
+
+@noindent
+generates the following code:
+
+@example
+.stabs "g_pf:G24=*25=f1",32,0,0,0
+ .common _g_pf,4,"bss"
+@end example
+
+The variable defines a new type, 24, which is a pointer to another new
+type, 25, which is a function returning @code{int}.
+
+@node Symbol Tables
+@chapter Symbol Information in Symbol Tables
+
+This chapter describes the format of symbol table entries
+and how stab assembler directives map to them. It also describes the
+transformations that the assembler and linker make on data from stabs.
+
+@menu
+* Symbol Table Format::
+* Transformations On Symbol Tables::
+@end menu
+
+@node Symbol Table Format
+@section Symbol Table Format
+
+Each time the assembler encounters a stab directive, it puts
+each field of the stab into a corresponding field in a symbol table
+entry of its output file. If the stab contains a string field, the
+symbol table entry for that stab points to a string table entry
+containing the string data from the stab. Assembler labels become
+relocatable addresses. Symbol table entries in a.out have the format:
+
+@c FIXME: should refer to external, not internal.
+@example
+struct internal_nlist @{
+ unsigned long n_strx; /* index into string table of name */
+ unsigned char n_type; /* type of symbol */
+ unsigned char n_other; /* misc info (usually empty) */
+ unsigned short n_desc; /* description field */
+ bfd_vma n_value; /* value of symbol */
+@};
+@end example
+
+If the stab has a string, the @code{n_strx} field holds the offset in
+bytes of the string within the string table. The string is terminated
+by a NUL character. If the stab lacks a string (for example, it was
+produced by a @code{.stabn} or @code{.stabd} directive), the
+@code{n_strx} field is zero.
+
+Symbol table entries with @code{n_type} field values greater than 0x1f
+originated as stabs generated by the compiler (with one random
+exception). The other entries were placed in the symbol table of the
+executable by the assembler or the linker.
+
+@node Transformations On Symbol Tables
+@section Transformations on Symbol Tables
+
+The linker concatenates object files and does fixups of externally
+defined symbols.
+
+You can see the transformations made on stab data by the assembler and
+linker by examining the symbol table after each pass of the build. To
+do this, use @samp{nm -ap}, which dumps the symbol table, including
+debugging information, unsorted. For stab entries the columns are:
+@var{value}, @var{other}, @var{desc}, @var{type}, @var{string}. For
+assembler and linker symbols, the columns are: @var{value}, @var{type},
+@var{string}.
+
+The low 5 bits of the stab type tell the linker how to relocate the
+value of the stab. Thus for stab types like @code{N_RSYM} and
+@code{N_LSYM}, where the value is an offset or a register number, the
+low 5 bits are @code{N_ABS}, which tells the linker not to relocate the
+value.
+
+Where the value of a stab contains an assembly language label,
+it is transformed by each build step. The assembler turns it into a
+relocatable address and the linker turns it into an absolute address.
+
+@menu
+* Transformations On Static Variables::
+* Transformations On Global Variables::
+* ELF Transformations:: In ELF, things are a bit different.
+@end menu
+
+@node Transformations On Static Variables
+@subsection Transformations on Static Variables
+
+This source line defines a static variable at file scope:
+
+@example
+static int s_g_repeat
+@end example
+
+@noindent
+The following stab describes the symbol:
+
+@example
+.stabs "s_g_repeat:S1",38,0,0,_s_g_repeat
+@end example
+
+@noindent
+The assembler transforms the stab into this symbol table entry in the
+@file{.o} file. The location is expressed as a data segment offset.
+
+@example
+00000084 - 00 0000 STSYM s_g_repeat:S1
+@end example
+
+@noindent
+In the symbol table entry from the executable, the linker has made the
+relocatable address absolute.
+
+@example
+0000e00c - 00 0000 STSYM s_g_repeat:S1
+@end example
+
+@node Transformations On Global Variables
+@subsection Transformations on Global Variables
+
+Stabs for global variables do not contain location information. In
+this case, the debugger finds location information in the assembler or
+linker symbol table entry describing the variable. The source line:
+
+@example
+char g_foo = 'c';
+@end example
+
+@noindent
+generates the stab:
+
+@example
+.stabs "g_foo:G2",32,0,0,0
+@end example
+
+The variable is represented by two symbol table entries in the object
+file (see below). The first one originated as a stab. The second one
+is an external symbol. The upper case @samp{D} signifies that the
+@code{n_type} field of the symbol table contains 7, @code{N_DATA} with
+local linkage. The stab's value is zero since the value is not used for
+@code{N_GSYM} stabs. The value of the linker symbol is the relocatable
+address corresponding to the variable.
+
+@example
+00000000 - 00 0000 GSYM g_foo:G2
+00000080 D _g_foo
+@end example
+
+@noindent
+These entries as transformed by the linker. The linker symbol table
+entry now holds an absolute address:
+
+@example
+00000000 - 00 0000 GSYM g_foo:G2
+@dots{}
+0000e008 D _g_foo
+@end example
+
+@node ELF Transformations
+@subsection Transformations of Stabs in ELF Files
+
+For ELF files, use @code{objdump --stabs} instead of @code{nm} to show
+the stabs in an object or executable file. @code{objdump} is a GNU
+utility; Sun does not provide any equivalent.
+
+The following example is for a stab whose value is an address is
+relative to the compilation unit (@pxref{Stabs In ELF}). For example,
+if the source line
+
+@example
+static int ld = 5;
+@end example
+
+appears within a function, then the assembly language output from the
+compiler contains:
+
+@example
+.Ddata.data:
+@dots{}
+ .stabs "ld:V(0,3)",0x26,0,4,.L18-Ddata.data # @r{0x26 is N_STSYM}
+@dots{}
+.L18:
+ .align 4
+ .word 0x5
+@end example
+
+Because the value is formed by subtracting one symbol from another, the
+value is absolute, not relocatable, and so the object file contains
+
+@example
+Symnum n_type n_othr n_desc n_value n_strx String
+31 STSYM 0 4 00000004 680 ld:V(0,3)
+@end example
+
+without any relocations, and the executable file also contains
+
+@example
+Symnum n_type n_othr n_desc n_value n_strx String
+31 STSYM 0 4 00000004 680 ld:V(0,3)
+@end example
+
+@node Cplusplus
+@chapter GNU C++ Stabs
+
+@menu
+* Basic Cplusplus Types::
+* Simple Classes::
+* Class Instance::
+* Methods:: Method definition
+* Protections::
+* Method Modifiers::
+* Virtual Methods::
+* Inheritence::
+* Virtual Base Classes::
+* Static Members::
+@end menu
+
+Type descriptors added for C++ descriptions:
+
+@table @code
+@item #
+method type (@code{##} if minimal debug)
+
+@item @@
+Member (class and variable) type. It is followed by type information
+for the offset basetype, a comma, and type information for the type of
+the field being pointed to. (FIXME: this is acknowledged to be
+gibberish. Can anyone say what really goes here?).
+
+Note that there is a conflict between this and type attributes
+(@pxref{String Field}); both use type descriptor @samp{@@}.
+Fortunately, the @samp{@@} type descriptor used in this C++ sense always
+will be followed by a digit, @samp{(}, or @samp{-}, and type attributes
+never start with those things.
+@end table
+
+@node Basic Cplusplus Types
+@section Basic Types For C++
+
+<< the examples that follow are based on a01.C >>
+
+
+C++ adds two more builtin types to the set defined for C. These are
+the unknown type and the vtable record type. The unknown type, type
+16, is defined in terms of itself like the void type.
+
+The vtable record type, type 17, is defined as a structure type and
+then as a structure tag. The structure has four fields: delta, index,
+pfn, and delta2. pfn is the function pointer.
+
+<< In boilerplate $vtbl_ptr_type, what are the fields delta,
+index, and delta2 used for? >>
+
+This basic type is present in all C++ programs even if there are no
+virtual methods defined.
+
+@display
+.stabs "struct_name:sym_desc(type)type_def(17)=type_desc(struct)struct_bytes(8)
+ elem_name(delta):type_ref(short int),bit_offset(0),field_bits(16);
+ elem_name(index):type_ref(short int),bit_offset(16),field_bits(16);
+ elem_name(pfn):type_def(18)=type_desc(ptr to)type_ref(void),
+ bit_offset(32),field_bits(32);
+ elem_name(delta2):type_def(short int);bit_offset(32),field_bits(16);;"
+ N_LSYM, NIL, NIL
+@end display
+
+@smallexample
+.stabs "$vtbl_ptr_type:t17=s8
+ delta:6,0,16;index:6,16,16;pfn:18=*15,32,32;delta2:6,32,16;;"
+ ,128,0,0,0
+@end smallexample
+
+@display
+.stabs "name:sym_dec(struct tag)type_ref($vtbl_ptr_type)",N_LSYM,NIL,NIL,NIL
+@end display
+
+@example
+.stabs "$vtbl_ptr_type:T17",128,0,0,0
+@end example
+
+@node Simple Classes
+@section Simple Class Definition
+
+The stabs describing C++ language features are an extension of the
+stabs describing C. Stabs representing C++ class types elaborate
+extensively on the stab format used to describe structure types in C.
+Stabs representing class type variables look just like stabs
+representing C language variables.
+
+Consider the following very simple class definition.
+
+@example
+class baseA @{
+public:
+ int Adat;
+ int Ameth(int in, char other);
+@};
+@end example
+
+The class @code{baseA} is represented by two stabs. The first stab describes
+the class as a structure type. The second stab describes a structure
+tag of the class type. Both stabs are of stab type @code{N_LSYM}. Since the
+stab is not located between an @code{N_FUN} and an @code{N_LBRAC} stab this indicates
+that the class is defined at file scope. If it were, then the @code{N_LSYM}
+would signify a local variable.
+
+A stab describing a C++ class type is similar in format to a stab
+describing a C struct, with each class member shown as a field in the
+structure. The part of the struct format describing fields is
+expanded to include extra information relevent to C++ class members.
+In addition, if the class has multiple base classes or virtual
+functions the struct format outside of the field parts is also
+augmented.
+
+In this simple example the field part of the C++ class stab
+representing member data looks just like the field part of a C struct
+stab. The section on protections describes how its format is
+sometimes extended for member data.
+
+The field part of a C++ class stab representing a member function
+differs substantially from the field part of a C struct stab. It
+still begins with @samp{name:} but then goes on to define a new type number
+for the member function, describe its return type, its argument types,
+its protection level, any qualifiers applied to the method definition,
+and whether the method is virtual or not. If the method is virtual
+then the method description goes on to give the vtable index of the
+method, and the type number of the first base class defining the
+method.
+
+When the field name is a method name it is followed by two colons rather
+than one. This is followed by a new type definition for the method.
+This is a number followed by an equal sign and the type descriptor
+@samp{#}, indicating a method type, and a second @samp{#}, indicating
+that this is the @dfn{minimal} type of method definition used by GCC2,
+not larger method definitions used by earlier versions of GCC. This is
+followed by a type reference showing the return type of the method and a
+semi-colon.
+
+The format of an overloaded operator method name differs from that of
+other methods. It is @samp{op$::@var{operator-name}.} where
+@var{operator-name} is the operator name such as @samp{+} or @samp{+=}.
+The name ends with a period, and any characters except the period can
+occur in the @var{operator-name} string.
+
+The next part of the method description represents the arguments to the
+method, preceeded by a colon and ending with a semi-colon. The types of
+the arguments are expressed in the same way argument types are expressed
+in C++ name mangling. In this example an @code{int} and a @code{char}
+map to @samp{ic}.
+
+This is followed by a number, a letter, and an asterisk or period,
+followed by another semicolon. The number indicates the protections
+that apply to the member function. Here the 2 means public. The
+letter encodes any qualifier applied to the method definition. In
+this case, @samp{A} means that it is a normal function definition. The dot
+shows that the method is not virtual. The sections that follow
+elaborate further on these fields and describe the additional
+information present for virtual methods.
+
+
+@display
+.stabs "class_name:sym_desc(type)type_def(20)=type_desc(struct)struct_bytes(4)
+ field_name(Adat):type(int),bit_offset(0),field_bits(32);
+
+ method_name(Ameth)::type_def(21)=type_desc(method)return_type(int);
+ :arg_types(int char);
+ protection(public)qualifier(normal)virtual(no);;"
+ N_LSYM,NIL,NIL,NIL
+@end display
+
+@smallexample
+.stabs "baseA:t20=s4Adat:1,0,32;Ameth::21=##1;:ic;2A.;;",128,0,0,0
+
+.stabs "class_name:sym_desc(struct tag)",N_LSYM,NIL,NIL,NIL
+
+.stabs "baseA:T20",128,0,0,0
+@end smallexample
+
+@node Class Instance
+@section Class Instance
+
+As shown above, describing even a simple C++ class definition is
+accomplished by massively extending the stab format used in C to
+describe structure types. However, once the class is defined, C stabs
+with no modifications can be used to describe class instances. The
+following source:
+
+@example
+main () @{
+ baseA AbaseA;
+@}
+@end example
+
+@noindent
+yields the following stab describing the class instance. It looks no
+different from a standard C stab describing a local variable.
+
+@display
+.stabs "name:type_ref(baseA)", N_LSYM, NIL, NIL, frame_ptr_offset
+@end display
+
+@example
+.stabs "AbaseA:20",128,0,0,-20
+@end example
+
+@node Methods
+@section Method Definition
+
+The class definition shown above declares Ameth. The C++ source below
+defines Ameth:
+
+@example
+int
+baseA::Ameth(int in, char other)
+@{
+ return in;
+@};
+@end example
+
+
+This method definition yields three stabs following the code of the
+method. One stab describes the method itself and following two describe
+its parameters. Although there is only one formal argument all methods
+have an implicit argument which is the @code{this} pointer. The @code{this}
+pointer is a pointer to the object on which the method was called. Note
+that the method name is mangled to encode the class name and argument
+types. Name mangling is described in the @sc{arm} (@cite{The Annotated
+C++ Reference Manual}, by Ellis and Stroustrup, @sc{isbn}
+0-201-51459-1); @file{gpcompare.texi} in Cygnus GCC distributions
+describes the differences between GNU mangling and @sc{arm}
+mangling.
+@c FIXME: Use @xref, especially if this is generally installed in the
+@c info tree.
+@c FIXME: This information should be in a net release, either of GCC or
+@c GDB. But gpcompare.texi doesn't seem to be in the FSF GCC.
+
+@example
+.stabs "name:symbol_desriptor(global function)return_type(int)",
+ N_FUN, NIL, NIL, code_addr_of_method_start
+
+.stabs "Ameth__5baseAic:F1",36,0,0,_Ameth__5baseAic
+@end example
+
+Here is the stab for the @code{this} pointer implicit argument. The
+name of the @code{this} pointer is always @code{this}. Type 19, the
+@code{this} pointer is defined as a pointer to type 20, @code{baseA},
+but a stab defining @code{baseA} has not yet been emited. Since the
+compiler knows it will be emited shortly, here it just outputs a cross
+reference to the undefined symbol, by prefixing the symbol name with
+@samp{xs}.
+
+@example
+.stabs "name:sym_desc(register param)type_def(19)=
+ type_desc(ptr to)type_ref(baseA)=
+ type_desc(cross-reference to)baseA:",N_RSYM,NIL,NIL,register_number
+
+.stabs "this:P19=*20=xsbaseA:",64,0,0,8
+@end example
+
+The stab for the explicit integer argument looks just like a parameter
+to a C function. The last field of the stab is the offset from the
+argument pointer, which in most systems is the same as the frame
+pointer.
+
+@example
+.stabs "name:sym_desc(value parameter)type_ref(int)",
+ N_PSYM,NIL,NIL,offset_from_arg_ptr
+
+.stabs "in:p1",160,0,0,72
+@end example
+
+<< The examples that follow are based on A1.C >>
+
+@node Protections
+@section Protections
+
+
+In the simple class definition shown above all member data and
+functions were publicly accessable. The example that follows
+contrasts public, protected and privately accessable fields and shows
+how these protections are encoded in C++ stabs.
+
+@c FIXME: What does "part of the string" mean?
+Protections for class member data are signified by two characters
+embedded in the stab defining the class type. These characters are
+located after the name: part of the string. @samp{/0} means private,
+@samp{/1} means protected, and @samp{/2} means public. If these
+characters are omited this means that the member is public. The
+following C++ source:
+
+@example
+class all_data @{
+private:
+ int priv_dat;
+protected:
+ char prot_dat;
+public:
+ float pub_dat;
+@};
+@end example
+
+@noindent
+generates the following stab to describe the class type all_data.
+
+@display
+.stabs "class_name:sym_desc(type)type_def(19)=type_desc(struct)struct_bytes
+ data_name:/protection(private)type_ref(int),bit_offset,num_bits;
+ data_name:/protection(protected)type_ref(char),bit_offset,num_bits;
+ data_name:(/num omited, private)type_ref(float),bit_offset,num_bits;;"
+ N_LSYM,NIL,NIL,NIL
+@end display
+
+@smallexample
+.stabs "all_data:t19=s12
+ priv_dat:/01,0,32;prot_dat:/12,32,8;pub_dat:12,64,32;;",128,0,0,0
+@end smallexample
+
+Protections for member functions are signified by one digit embeded in
+the field part of the stab describing the method. The digit is 0 if
+private, 1 if protected and 2 if public. Consider the C++ class
+definition below:
+
+@example
+class all_methods @{
+private:
+ int priv_meth(int in)@{return in;@};
+protected:
+ char protMeth(char in)@{return in;@};
+public:
+ float pubMeth(float in)@{return in;@};
+@};
+@end example
+
+It generates the following stab. The digit in question is to the left
+of an @samp{A} in each case. Notice also that in this case two symbol
+descriptors apply to the class name struct tag and struct type.
+
+@display
+.stabs "class_name:sym_desc(struct tag&type)type_def(21)=
+ sym_desc(struct)struct_bytes(1)
+ meth_name::type_def(22)=sym_desc(method)returning(int);
+ :args(int);protection(private)modifier(normal)virtual(no);
+ meth_name::type_def(23)=sym_desc(method)returning(char);
+ :args(char);protection(protected)modifier(normal)virual(no);
+ meth_name::type_def(24)=sym_desc(method)returning(float);
+ :args(float);protection(public)modifier(normal)virtual(no);;",
+ N_LSYM,NIL,NIL,NIL
+@end display
+
+@smallexample
+.stabs "all_methods:Tt21=s1priv_meth::22=##1;:i;0A.;protMeth::23=##2;:c;1A.;
+ pubMeth::24=##12;:f;2A.;;",128,0,0,0
+@end smallexample
+
+@node Method Modifiers
+@section Method Modifiers (@code{const}, @code{volatile}, @code{const volatile})
+
+<< based on a6.C >>
+
+In the class example described above all the methods have the normal
+modifier. This method modifier information is located just after the
+protection information for the method. This field has four possible
+character values. Normal methods use @samp{A}, const methods use
+@samp{B}, volatile methods use @samp{C}, and const volatile methods use
+@samp{D}. Consider the class definition below:
+
+@example
+class A @{
+public:
+ int ConstMeth (int arg) const @{ return arg; @};
+ char VolatileMeth (char arg) volatile @{ return arg; @};
+ float ConstVolMeth (float arg) const volatile @{return arg; @};
+@};
+@end example
+
+This class is described by the following stab:
+
+@display
+.stabs "class(A):sym_desc(struct)type_def(20)=type_desc(struct)struct_bytes(1)
+ meth_name(ConstMeth)::type_def(21)sym_desc(method)
+ returning(int);:arg(int);protection(public)modifier(const)virtual(no);
+ meth_name(VolatileMeth)::type_def(22)=sym_desc(method)
+ returning(char);:arg(char);protection(public)modifier(volatile)virt(no)
+ meth_name(ConstVolMeth)::type_def(23)=sym_desc(method)
+ returning(float);:arg(float);protection(public)modifer(const volatile)
+ virtual(no);;", @dots{}
+@end display
+
+@example
+.stabs "A:T20=s1ConstMeth::21=##1;:i;2B.;VolatileMeth::22=##2;:c;2C.;
+ ConstVolMeth::23=##12;:f;2D.;;",128,0,0,0
+@end example
+
+@node Virtual Methods
+@section Virtual Methods
+
+<< The following examples are based on a4.C >>
+
+The presence of virtual methods in a class definition adds additional
+data to the class description. The extra data is appended to the
+description of the virtual method and to the end of the class
+description. Consider the class definition below:
+
+@example
+class A @{
+public:
+ int Adat;
+ virtual int A_virt (int arg) @{ return arg; @};
+@};
+@end example
+
+This results in the stab below describing class A. It defines a new
+type (20) which is an 8 byte structure. The first field of the class
+struct is @samp{Adat}, an integer, starting at structure offset 0 and
+occupying 32 bits.
+
+The second field in the class struct is not explicitly defined by the
+C++ class definition but is implied by the fact that the class
+contains a virtual method. This field is the vtable pointer. The
+name of the vtable pointer field starts with @samp{$vf} and continues with a
+type reference to the class it is part of. In this example the type
+reference for class A is 20 so the name of its vtable pointer field is
+@samp{$vf20}, followed by the usual colon.
+
+Next there is a type definition for the vtable pointer type (21).
+This is in turn defined as a pointer to another new type (22).
+
+Type 22 is the vtable itself, which is defined as an array, indexed by
+a range of integers between 0 and 1, and whose elements are of type
+17. Type 17 was the vtable record type defined by the boilerplate C++
+type definitions, as shown earlier.
+
+The bit offset of the vtable pointer field is 32. The number of bits
+in the field are not specified when the field is a vtable pointer.
+
+Next is the method definition for the virtual member function @code{A_virt}.
+Its description starts out using the same format as the non-virtual
+member functions described above, except instead of a dot after the
+@samp{A} there is an asterisk, indicating that the function is virtual.
+Since is is virtual some addition information is appended to the end
+of the method description.
+
+The first number represents the vtable index of the method. This is a
+32 bit unsigned number with the high bit set, followed by a
+semi-colon.
+
+The second number is a type reference to the first base class in the
+inheritence hierarchy defining the virtual member function. In this
+case the class stab describes a base class so the virtual function is
+not overriding any other definition of the method. Therefore the
+reference is to the type number of the class that the stab is
+describing (20).
+
+This is followed by three semi-colons. One marks the end of the
+current sub-section, one marks the end of the method field, and the
+third marks the end of the struct definition.
+
+For classes containing virtual functions the very last section of the
+string part of the stab holds a type reference to the first base
+class. This is preceeded by @samp{~%} and followed by a final semi-colon.
+
+@display
+.stabs "class_name(A):type_def(20)=sym_desc(struct)struct_bytes(8)
+ field_name(Adat):type_ref(int),bit_offset(0),field_bits(32);
+ field_name(A virt func ptr):type_def(21)=type_desc(ptr to)type_def(22)=
+ sym_desc(array)index_type_ref(range of int from 0 to 1);
+ elem_type_ref(vtbl elem type),
+ bit_offset(32);
+ meth_name(A_virt)::typedef(23)=sym_desc(method)returning(int);
+ :arg_type(int),protection(public)normal(yes)virtual(yes)
+ vtable_index(1);class_first_defining(A);;;~%first_base(A);",
+ N_LSYM,NIL,NIL,NIL
+@end display
+
+@c FIXME: bogus line break.
+@example
+.stabs "A:t20=s8Adat:1,0,32;$vf20:21=*22=ar1;0;1;17,32;
+ A_virt::23=##1;:i;2A*-2147483647;20;;;~%20;",128,0,0,0
+@end example
+
+@node Inheritence
+@section Inheritence
+
+Stabs describing C++ derived classes include additional sections that
+describe the inheritence hierarchy of the class. A derived class stab
+also encodes the number of base classes. For each base class it tells
+if the base class is virtual or not, and if the inheritence is private
+or public. It also gives the offset into the object of the portion of
+the object corresponding to each base class.
+
+This additional information is embeded in the class stab following the
+number of bytes in the struct. First the number of base classes
+appears bracketed by an exclamation point and a comma.
+
+Then for each base type there repeats a series: two digits, a number,
+a comma, another number, and a semi-colon.
+
+The first of the two digits is 1 if the base class is virtual and 0 if
+not. The second digit is 2 if the derivation is public and 0 if not.
+
+The number following the first two digits is the offset from the start
+of the object to the part of the object pertaining to the base class.
+
+After the comma, the second number is a type_descriptor for the base
+type. Finally a semi-colon ends the series, which repeats for each
+base class.
+
+The source below defines three base classes @code{A}, @code{B}, and
+@code{C} and the derived class @code{D}.
+
+
+@example
+class A @{
+public:
+ int Adat;
+ virtual int A_virt (int arg) @{ return arg; @};
+@};
+
+class B @{
+public:
+ int B_dat;
+ virtual int B_virt (int arg) @{return arg; @};
+@};
+
+class C @{
+public:
+ int Cdat;
+ virtual int C_virt (int arg) @{return arg; @};
+@};
+
+class D : A, virtual B, public C @{
+public:
+ int Ddat;
+ virtual int A_virt (int arg ) @{ return arg+1; @};
+ virtual int B_virt (int arg) @{ return arg+2; @};
+ virtual int C_virt (int arg) @{ return arg+3; @};
+ virtual int D_virt (int arg) @{ return arg; @};
+@};
+@end example
+
+Class stabs similar to the ones described earlier are generated for
+each base class.
+
+@c FIXME!!! the linebreaks in the following example probably make the
+@c examples literally unusable, but I don't know any other way to get
+@c them on the page.
+@c One solution would be to put some of the type definitions into
+@c separate stabs, even if that's not exactly what the compiler actually
+@c emits.
+@smallexample
+.stabs "A:T20=s8Adat:1,0,32;$vf20:21=*22=ar1;0;1;17,32;
+ A_virt::23=##1;:i;2A*-2147483647;20;;;~%20;",128,0,0,0
+
+.stabs "B:Tt25=s8Bdat:1,0,32;$vf25:21,32;B_virt::26=##1;
+ :i;2A*-2147483647;25;;;~%25;",128,0,0,0
+
+.stabs "C:Tt28=s8Cdat:1,0,32;$vf28:21,32;C_virt::29=##1;
+ :i;2A*-2147483647;28;;;~%28;",128,0,0,0
+@end smallexample
+
+In the stab describing derived class @code{D} below, the information about
+the derivation of this class is encoded as follows.
+
+@display
+.stabs "derived_class_name:symbol_descriptors(struct tag&type)=
+ type_descriptor(struct)struct_bytes(32)!num_bases(3),
+ base_virtual(no)inheritence_public(no)base_offset(0),
+ base_class_type_ref(A);
+ base_virtual(yes)inheritence_public(no)base_offset(NIL),
+ base_class_type_ref(B);
+ base_virtual(no)inheritence_public(yes)base_offset(64),
+ base_class_type_ref(C); @dots{}
+@end display
+
+@c FIXME! fake linebreaks.
+@smallexample
+.stabs "D:Tt31=s32!3,000,20;100,25;0264,28;$vb25:24,128;Ddat:
+ 1,160,32;A_virt::32=##1;:i;2A*-2147483647;20;;B_virt:
+ :32:i;2A*-2147483647;25;;C_virt::32:i;2A*-2147483647;
+ 28;;D_virt::32:i;2A*-2147483646;31;;;~%20;",128,0,0,0
+@end smallexample
+
+@node Virtual Base Classes
+@section Virtual Base Classes
+
+A derived class object consists of a concatination in memory of the data
+areas defined by each base class, starting with the leftmost and ending
+with the rightmost in the list of base classes. The exception to this
+rule is for virtual inheritence. In the example above, class @code{D}
+inherits virtually from base class @code{B}. This means that an
+instance of a @code{D} object will not contain its own @code{B} part but
+merely a pointer to a @code{B} part, known as a virtual base pointer.
+
+In a derived class stab, the base offset part of the derivation
+information, described above, shows how the base class parts are
+ordered. The base offset for a virtual base class is always given as 0.
+Notice that the base offset for @code{B} is given as 0 even though
+@code{B} is not the first base class. The first base class @code{A}
+starts at offset 0.
+
+The field information part of the stab for class @code{D} describes the field
+which is the pointer to the virtual base class @code{B}. The vbase pointer
+name is @samp{$vb} followed by a type reference to the virtual base class.
+Since the type id for @code{B} in this example is 25, the vbase pointer name
+is @samp{$vb25}.
+
+@c FIXME!! fake linebreaks below
+@smallexample
+.stabs "D:Tt31=s32!3,000,20;100,25;0264,28;$vb25:24,128;Ddat:1,
+ 160,32;A_virt::32=##1;:i;2A*-2147483647;20;;B_virt::32:i;
+ 2A*-2147483647;25;;C_virt::32:i;2A*-2147483647;28;;D_virt:
+ :32:i;2A*-2147483646;31;;;~%20;",128,0,0,0
+@end smallexample
+
+Following the name and a semicolon is a type reference describing the
+type of the virtual base class pointer, in this case 24. Type 24 was
+defined earlier as the type of the @code{B} class @code{this} pointer. The
+@code{this} pointer for a class is a pointer to the class type.
+
+@example
+.stabs "this:P24=*25=xsB:",64,0,0,8
+@end example
+
+Finally the field offset part of the vbase pointer field description
+shows that the vbase pointer is the first field in the @code{D} object,
+before any data fields defined by the class. The layout of a @code{D}
+class object is a follows, @code{Adat} at 0, the vtable pointer for
+@code{A} at 32, @code{Cdat} at 64, the vtable pointer for C at 96, the
+virtual base pointer for @code{B} at 128, and @code{Ddat} at 160.
+
+
+@node Static Members
+@section Static Members
+
+The data area for a class is a concatenation of the space used by the
+data members of the class. If the class has virtual methods, a vtable
+pointer follows the class data. The field offset part of each field
+description in the class stab shows this ordering.
+
+<< How is this reflected in stabs? See Cygnus bug #677 for some info. >>
+
+@node Stab Types
+@appendix Table of Stab Types
+
+The following are all the possible values for the stab type field, for
+@code{a.out} files, in numeric order. This does not apply to XCOFF, but
+it does apply to stabs in ELF. Stabs in ECOFF use these values but add
+0x8f300 to distinguish them from non-stab symbols.
+
+The symbolic names are defined in the file @file{include/aout/stabs.def}.
+
+@menu
+* Non-Stab Symbol Types:: Types from 0 to 0x1f
+* Stab Symbol Types:: Types from 0x20 to 0xff
+@end menu
+
+@node Non-Stab Symbol Types
+@appendixsec Non-Stab Symbol Types
+
+The following types are used by the linker and assembler, not by stab
+directives. Since this document does not attempt to describe aspects of
+object file format other than the debugging format, no details are
+given.
+
+@c Try to get most of these to fit on a single line.
+@iftex
+@tableindent=1.5in
+@end iftex
+
+@table @code
+@item 0x0 N_UNDF
+Undefined symbol
+
+@item 0x2 N_ABS
+File scope absolute symbol
+
+@item 0x3 N_ABS | N_EXT
+External absolute symbol
+
+@item 0x4 N_TEXT
+File scope text symbol
+
+@item 0x5 N_TEXT | N_EXT
+External text symbol
+
+@item 0x6 N_DATA
+File scope data symbol
+
+@item 0x7 N_DATA | N_EXT
+External data symbol
+
+@item 0x8 N_BSS
+File scope BSS symbol
+
+@item 0x9 N_BSS | N_EXT
+External BSS symbol
+
+@item 0x0c N_FN_SEQ
+Same as @code{N_FN}, for Sequent compilers
+
+@item 0x0a N_INDR
+Symbol is indirected to another symbol
+
+@item 0x12 N_COMM
+Common---visible after shared library dynamic link
+
+@item 0x14 N_SETA
+Absolute set element
+
+@item 0x16 N_SETT
+Text segment set element
+
+@item 0x18 N_SETD
+Data segment set element
+
+@item 0x1a N_SETB
+BSS segment set element
+
+@item 0x1c N_SETV
+Pointer to set vector
+
+@item 0x1e N_WARNING
+Print a warning message during linking
+
+@item 0x1f N_FN
+File name of a @file{.o} file
+@end table
+
+@node Stab Symbol Types
+@appendixsec Stab Symbol Types
+
+The following symbol types indicate that this is a stab. This is the
+full list of stab numbers, including stab types that are used in
+languages other than C.
+
+@table @code
+@item 0x20 N_GSYM
+Global symbol; see @ref{Global Variables}.
+
+@item 0x22 N_FNAME
+Function name (for BSD Fortran); see @ref{Procedures}.
+
+@item 0x24 N_FUN
+Function name (@pxref{Procedures}) or text segment variable
+(@pxref{Statics}).
+
+@item 0x26 N_STSYM
+Data segment file-scope variable; see @ref{Statics}.
+
+@item 0x28 N_LCSYM
+BSS segment file-scope variable; see @ref{Statics}.
+
+@item 0x2a N_MAIN
+Name of main routine; see @ref{Main Program}.
+
+@item 0x2c N_ROSYM
+Variable in @code{.rodata} section; see @ref{Statics}.
+
+@item 0x30 N_PC
+Global symbol (for Pascal); see @ref{N_PC}.
+
+@item 0x32 N_NSYMS
+Number of symbols (according to Ultrix V4.0); see @ref{N_NSYMS}.
+
+@item 0x34 N_NOMAP
+No DST map; see @ref{N_NOMAP}.
+
+@c FIXME: describe this solaris feature in the body of the text (see
+@c comments in include/aout/stab.def).
+@item 0x38 N_OBJ
+Object file (Solaris2).
+
+@c See include/aout/stab.def for (a little) more info.
+@item 0x3c N_OPT
+Debugger options (Solaris2).
+
+@item 0x40 N_RSYM
+Register variable; see @ref{Register Variables}.
+
+@item 0x42 N_M2C
+Modula-2 compilation unit; see @ref{N_M2C}.
+
+@item 0x44 N_SLINE
+Line number in text segment; see @ref{Line Numbers}.
+
+@item 0x46 N_DSLINE
+Line number in data segment; see @ref{Line Numbers}.
+
+@item 0x48 N_BSLINE
+Line number in bss segment; see @ref{Line Numbers}.
+
+@item 0x48 N_BROWS
+Sun source code browser, path to @file{.cb} file; see @ref{N_BROWS}.
+
+@item 0x4a N_DEFD
+GNU Modula2 definition module dependency; see @ref{N_DEFD}.
+
+@item 0x4c N_FLINE
+Function start/body/end line numbers (Solaris2).
+
+@item 0x50 N_EHDECL
+GNU C++ exception variable; see @ref{N_EHDECL}.
+
+@item 0x50 N_MOD2
+Modula2 info "for imc" (according to Ultrix V4.0); see @ref{N_MOD2}.
+
+@item 0x54 N_CATCH
+GNU C++ @code{catch} clause; see @ref{N_CATCH}.
+
+@item 0x60 N_SSYM
+Structure of union element; see @ref{N_SSYM}.
+
+@item 0x62 N_ENDM
+Last stab for module (Solaris2).
+
+@item 0x64 N_SO
+Path and name of source file; see @ref{Source Files}.
+
+@item 0x80 N_LSYM
+Stack variable (@pxref{Stack Variables}) or type (@pxref{Typedefs}).
+
+@item 0x82 N_BINCL
+Beginning of an include file (Sun only); see @ref{Include Files}.
+
+@item 0x84 N_SOL
+Name of include file; see @ref{Include Files}.
+
+@item 0xa0 N_PSYM
+Parameter variable; see @ref{Parameters}.
+
+@item 0xa2 N_EINCL
+End of an include file; see @ref{Include Files}.
+
+@item 0xa4 N_ENTRY
+Alternate entry point; see @ref{N_ENTRY}.
+
+@item 0xc0 N_LBRAC
+Beginning of a lexical block; see @ref{Block Structure}.
+
+@item 0xc2 N_EXCL
+Place holder for a deleted include file; see @ref{Include Files}.
+
+@item 0xc4 N_SCOPE
+Modula2 scope information (Sun linker); see @ref{N_SCOPE}.
+
+@item 0xe0 N_RBRAC
+End of a lexical block; see @ref{Block Structure}.
+
+@item 0xe2 N_BCOMM
+Begin named common block; see @ref{Common Blocks}.
+
+@item 0xe4 N_ECOMM
+End named common block; see @ref{Common Blocks}.
+
+@item 0xe8 N_ECOML
+Member of a common block; see @ref{Common Blocks}.
+
+@c FIXME: How does this really work? Move it to main body of document.
+@item 0xea N_WITH
+Pascal @code{with} statement: type,,0,0,offset (Solaris2).
+
+@item 0xf0 N_NBTEXT
+Gould non-base registers; see @ref{Gould}.
+
+@item 0xf2 N_NBDATA
+Gould non-base registers; see @ref{Gould}.
+
+@item 0xf4 N_NBBSS
+Gould non-base registers; see @ref{Gould}.
+
+@item 0xf6 N_NBSTS
+Gould non-base registers; see @ref{Gould}.
+
+@item 0xf8 N_NBLCS
+Gould non-base registers; see @ref{Gould}.
+@end table
+
+@c Restore the default table indent
+@iftex
+@tableindent=.8in
+@end iftex
+
+@node Symbol Descriptors
+@appendix Table of Symbol Descriptors
+
+The symbol descriptor is the character which follows the colon in many
+stabs, and which tells what kind of stab it is. @xref{String Field},
+for more information about their use.
+
+@c Please keep this alphabetical
+@table @code
+@c In TeX, this looks great, digit is in italics. But makeinfo insists
+@c on putting it in `', not realizing that @var should override @code.
+@c I don't know of any way to make makeinfo do the right thing. Seems
+@c like a makeinfo bug to me.
+@item @var{digit}
+@itemx (
+@itemx -
+Variable on the stack; see @ref{Stack Variables}.
+
+@item a
+Parameter passed by reference in register; see @ref{Reference Parameters}.
+
+@item b
+Based variable; see @ref{Based Variables}.
+
+@item c
+Constant; see @ref{Constants}.
+
+@item C
+Conformant array bound (Pascal, maybe other languages); @ref{Conformant
+Arrays}. Name of a caught exception (GNU C++). These can be
+distinguished because the latter uses @code{N_CATCH} and the former uses
+another symbol type.
+
+@item d
+Floating point register variable; see @ref{Register Variables}.
+
+@item D
+Parameter in floating point register; see @ref{Register Parameters}.
+
+@item f
+File scope function; see @ref{Procedures}.
+
+@item F
+Global function; see @ref{Procedures}.
+
+@item G
+Global variable; see @ref{Global Variables}.
+
+@item i
+@xref{Register Parameters}.
+
+@item I
+Internal (nested) procedure; see @ref{Nested Procedures}.
+
+@item J
+Internal (nested) function; see @ref{Nested Procedures}.
+
+@item L
+Label name (documented by AIX, no further information known).
+
+@item m
+Module; see @ref{Procedures}.
+
+@item p
+Argument list parameter; see @ref{Parameters}.
+
+@item pP
+@xref{Parameters}.
+
+@item pF
+Fortran Function parameter; see @ref{Parameters}.
+
+@item P
+Unfortunately, three separate meanings have been independently invented
+for this symbol descriptor. At least the GNU and Sun uses can be
+distinguished by the symbol type. Global Procedure (AIX) (symbol type
+used unknown); see @ref{Procedures}. Register parameter (GNU) (symbol
+type @code{N_PSYM}); see @ref{Parameters}. Prototype of function
+referenced by this file (Sun @code{acc}) (symbol type @code{N_FUN}).
+
+@item Q
+Static Procedure; see @ref{Procedures}.
+
+@item R
+Register parameter; see @ref{Register Parameters}.
+
+@item r
+Register variable; see @ref{Register Variables}.
+
+@item S
+File scope variable; see @ref{Statics}.
+
+@item t
+Type name; see @ref{Typedefs}.
+
+@item T
+Enumeration, structure, or union tag; see @ref{Typedefs}.
+
+@item v
+Parameter passed by reference; see @ref{Reference Parameters}.
+
+@item V
+Procedure scope static variable; see @ref{Statics}.
+
+@item x
+Conformant array; see @ref{Conformant Arrays}.
+
+@item X
+Function return variable; see @ref{Parameters}.
+@end table
+
+@node Type Descriptors
+@appendix Table of Type Descriptors
+
+The type descriptor is the character which follows the type number and
+an equals sign. It specifies what kind of type is being defined.
+@xref{String Field}, for more information about their use.
+
+@table @code
+@item @var{digit}
+@itemx (
+Type reference; see @ref{String Field}.
+
+@item -
+Reference to builtin type; see @ref{Negative Type Numbers}.
+
+@item #
+Method (C++); see @ref{Cplusplus}.
+
+@item *
+Pointer; see @ref{Miscellaneous Types}.
+
+@item &
+Reference (C++).
+
+@item @@
+Type Attributes (AIX); see @ref{String Field}. Member (class and variable)
+type (GNU C++); see @ref{Cplusplus}.
+
+@item a
+Array; see @ref{Arrays}.
+
+@item A
+Open array; see @ref{Arrays}.
+
+@item b
+Pascal space type (AIX); see @ref{Miscellaneous Types}. Builtin integer
+type (Sun); see @ref{Builtin Type Descriptors}.
+
+@item B
+Volatile-qualified type; see @ref{Miscellaneous Types}.
+
+@item c
+Complex builtin type; see @ref{Builtin Type Descriptors}.
+
+@item C
+COBOL Picture type. See AIX documentation for details.
+
+@item d
+File type; see @ref{Miscellaneous Types}.
+
+@item D
+N-dimensional dynamic array; see @ref{Arrays}.
+
+@item e
+Enumeration type; see @ref{Enumerations}.
+
+@item E
+N-dimensional subarray; see @ref{Arrays}.
+
+@item f
+Function type; see @ref{Function Types}.
+
+@item F
+Pascal function parameter; see @ref{Function Types}
+
+@item g
+Builtin floating point type; see @ref{Builtin Type Descriptors}.
+
+@item G
+COBOL Group. See AIX documentation for details.
+
+@item i
+Imported type; see @ref{Cross-References}.
+
+@item k
+Const-qualified type; see @ref{Miscellaneous Types}.
+
+@item K
+COBOL File Descriptor. See AIX documentation for details.
+
+@item M
+Multiple instance type; see @ref{Miscellaneous Types}.
+
+@item n
+String type; see @ref{Strings}.
+
+@item N
+Stringptr; see @ref{Strings}.
+
+@item o
+Opaque type; see @ref{Typedefs}.
+
+@item p
+Procedure; see @ref{Function Types}.
+
+@item P
+Packed array; see @ref{Arrays}.
+
+@item r
+Range type; see @ref{Subranges}.
+
+@item R
+Builtin floating type; see @ref{Builtin Type Descriptors} (Sun). Pascal
+subroutine parameter; see @ref{Function Types} (AIX). Detecting this
+conflict is possible with careful parsing (hint: a Pascal subroutine
+parameter type will always contain a comma, and a builtin type
+descriptor never will).
+
+@item s
+Structure type; see @ref{Structures}.
+
+@item S
+Set type; see @ref{Miscellaneous Types}.
+
+@item u
+Union; see @ref{Unions}.
+
+@item v
+Variant record. This is a Pascal and Modula-2 feature which is like a
+union within a struct in C. See AIX documentation for details.
+
+@item w
+Wide character; see @ref{Builtin Type Descriptors}.
+
+@item x
+Cross-reference; see @ref{Cross-References}.
+
+@item z
+gstring; see @ref{Strings}.
+@end table
+
+@node Expanded Reference
+@appendix Expanded Reference by Stab Type
+
+@c FIXME: This appendix should go away; see N_PSYM or N_SO for an example.
+
+For a full list of stab types, and cross-references to where they are
+described, see @ref{Stab Types}. This appendix just duplicates certain
+information from the main body of this document; eventually the
+information will all be in one place.
+
+Format of an entry:
+
+The first line is the symbol type (see @file{include/aout/stab.def}).
+
+The second line describes the language constructs the symbol type
+represents.
+
+The third line is the stab format with the significant stab fields
+named and the rest NIL.
+
+Subsequent lines expand upon the meaning and possible values for each
+significant stab field. @samp{#} stands in for the type descriptor.
+
+Finally, any further information.
+
+@menu
+* N_PC:: Pascal global symbol
+* N_NSYMS:: Number of symbols
+* N_NOMAP:: No DST map
+* N_M2C:: Modula-2 compilation unit
+* N_BROWS:: Path to .cb file for Sun source code browser
+* N_DEFD:: GNU Modula2 definition module dependency
+* N_EHDECL:: GNU C++ exception variable
+* N_MOD2:: Modula2 information "for imc"
+* N_CATCH:: GNU C++ "catch" clause
+* N_SSYM:: Structure or union element
+* N_ENTRY:: Alternate entry point
+* N_SCOPE:: Modula2 scope information (Sun only)
+* Gould:: non-base register symbols used on Gould systems
+* N_LENG:: Length of preceding entry
+@end menu
+
+@node N_PC
+@section N_PC
+
+@deffn @code{.stabs} N_PC
+@findex N_PC
+Global symbol (for Pascal).
+
+@example
+"name" -> "symbol_name" <<?>>
+value -> supposedly the line number (stab.def is skeptical)
+@end example
+
+@display
+@file{stabdump.c} says:
+
+global pascal symbol: name,,0,subtype,line
+<< subtype? >>
+@end display
+@end deffn
+
+@node N_NSYMS
+@section N_NSYMS
+
+@deffn @code{.stabn} N_NSYMS
+@findex N_NSYMS
+Number of symbols (according to Ultrix V4.0).
+
+@display
+ 0, files,,funcs,lines (stab.def)
+@end display
+@end deffn
+
+@node N_NOMAP
+@section N_NOMAP
+
+@deffn @code{.stabs} N_NOMAP
+@findex N_NOMAP
+No DST map for symbol (according to Ultrix V4.0). I think this means a
+variable has been optimized out.
+
+@display
+ name, ,0,type,ignored (stab.def)
+@end display
+@end deffn
+
+@node N_M2C
+@section N_M2C
+
+@deffn @code{.stabs} N_M2C
+@findex N_M2C
+Modula-2 compilation unit.
+
+@example
+"string" -> "unit_name,unit_time_stamp[,code_time_stamp]"
+desc -> unit_number
+value -> 0 (main unit)
+ 1 (any other unit)
+@end example
+@end deffn
+
+@node N_BROWS
+@section N_BROWS
+
+@deffn @code{.stabs} N_BROWS
+@findex N_BROWS
+Sun source code browser, path to @file{.cb} file
+
+<<?>>
+"path to associated @file{.cb} file"
+
+Note: N_BROWS has the same value as N_BSLINE.
+@end deffn
+
+@node N_DEFD
+@section N_DEFD
+
+@deffn @code{.stabn} N_DEFD
+@findex N_DEFD
+GNU Modula2 definition module dependency.
+
+GNU Modula-2 definition module dependency. The value is the
+modification time of the definition file. The other field is non-zero
+if it is imported with the GNU M2 keyword @code{%INITIALIZE}. Perhaps
+@code{N_M2C} can be used if there are enough empty fields?
+@end deffn
+
+@node N_EHDECL
+@section N_EHDECL
+
+@deffn @code{.stabs} N_EHDECL
+@findex N_EHDECL
+GNU C++ exception variable <<?>>.
+
+"@var{string} is variable name"
+
+Note: conflicts with @code{N_MOD2}.
+@end deffn
+
+@node N_MOD2
+@section N_MOD2
+
+@deffn @code{.stab?} N_MOD2
+@findex N_MOD2
+Modula2 info "for imc" (according to Ultrix V4.0)
+
+Note: conflicts with @code{N_EHDECL} <<?>>
+@end deffn
+
+@node N_CATCH
+@section N_CATCH
+
+@deffn @code{.stabn} N_CATCH
+@findex N_CATCH
+GNU C++ @code{catch} clause
+
+GNU C++ @code{catch} clause. The value is its address. The desc field
+is nonzero if this entry is immediately followed by a @code{CAUGHT} stab
+saying what exception was caught. Multiple @code{CAUGHT} stabs means
+that multiple exceptions can be caught here. If desc is 0, it means all
+exceptions are caught here.
+@end deffn
+
+@node N_SSYM
+@section N_SSYM
+
+@deffn @code{.stabn} N_SSYM
+@findex N_SSYM
+Structure or union element.
+
+The value is the offset in the structure.
+
+<<?looking at structs and unions in C I didn't see these>>
+@end deffn
+
+@node N_ENTRY
+@section N_ENTRY
+
+@deffn @code{.stabn} N_ENTRY
+@findex N_ENTRY
+Alternate entry point.
+The value is its address.
+<<?>>
+@end deffn
+
+@node N_SCOPE
+@section N_SCOPE
+
+@deffn @code{.stab?} N_SCOPE
+@findex N_SCOPE
+Modula2 scope information (Sun linker)
+<<?>>
+@end deffn
+
+@node Gould
+@section Non-base registers on Gould systems
+
+@deffn @code{.stab?} N_NBTEXT
+@deffnx @code{.stab?} N_NBDATA
+@deffnx @code{.stab?} N_NBBSS
+@deffnx @code{.stab?} N_NBSTS
+@deffnx @code{.stab?} N_NBLCS
+@findex N_NBTEXT
+@findex N_NBDATA
+@findex N_NBBSS
+@findex N_NBSTS
+@findex N_NBLCS
+These are used on Gould systems for non-base registers syms.
+
+However, the following values are not the values used by Gould; they are
+the values which GNU has been documenting for these values for a long
+time, without actually checking what Gould uses. I include these values
+only because perhaps some someone actually did something with the GNU
+information (I hope not, why GNU knowingly assigned wrong values to
+these in the header file is a complete mystery to me).
+
+@example
+240 0xf0 N_NBTEXT ??
+242 0xf2 N_NBDATA ??
+244 0xf4 N_NBBSS ??
+246 0xf6 N_NBSTS ??
+248 0xf8 N_NBLCS ??
+@end example
+@end deffn
+
+@node N_LENG
+@section N_LENG
+
+@deffn @code{.stabn} N_LENG
+@findex N_LENG
+Second symbol entry containing a length-value for the preceding entry.
+The value is the length.
+@end deffn
+
+@node Questions
+@appendix Questions and Anomalies
+
+@itemize @bullet
+@item
+@c I think this is changed in GCC 2.4.5 to put the line number there.
+For GNU C stabs defining local and global variables (@code{N_LSYM} and
+@code{N_GSYM}), the desc field is supposed to contain the source
+line number on which the variable is defined. In reality the desc
+field is always 0. (This behavior is defined in @file{dbxout.c} and
+putting a line number in desc is controlled by @samp{#ifdef
+WINNING_GDB}, which defaults to false). GDB supposedly uses this
+information if you say @samp{list @var{var}}. In reality, @var{var} can
+be a variable defined in the program and GDB says @samp{function
+@var{var} not defined}.
+
+@item
+In GNU C stabs, there seems to be no way to differentiate tag types:
+structures, unions, and enums (symbol descriptor @samp{T}) and typedefs
+(symbol descriptor @samp{t}) defined at file scope from types defined locally
+to a procedure or other more local scope. They all use the @code{N_LSYM}
+stab type. Types defined at procedure scope are emited after the
+@code{N_RBRAC} of the preceding function and before the code of the
+procedure in which they are defined. This is exactly the same as
+types defined in the source file between the two procedure bodies.
+GDB overcompensates by placing all types in block #1, the block for
+symbols of file scope. This is true for default, @samp{-ansi} and
+@samp{-traditional} compiler options. (Bugs gcc/1063, gdb/1066.)
+
+@item
+What ends the procedure scope? Is it the proc block's @code{N_RBRAC} or the
+next @code{N_FUN}? (I believe its the first.)
+
+@item
+@c FIXME: This should go with the other stuff about global variables.
+Global variable stabs don't have location information. This comes
+from the external symbol for the same variable. The external symbol
+has a leading underbar on the _name of the variable and the stab does
+not. How do we know these two symbol table entries are talking about
+the same symbol when their names are different? (Answer: the debugger
+knows that external symbols have leading underbars).
+
+@c FIXME: This is absurdly vague; there all kinds of differences, some
+@c of which are the same between gnu & sun, and some of which aren't.
+@c In particular, I'm pretty sure GCC works with Sun dbx by default.
+@c @item
+@c Can GCC be configured to output stabs the way the Sun compiler
+@c does, so that their native debugging tools work? <NO?> It doesn't by
+@c default. GDB reads either format of stab. (GCC or SunC). How about
+@c dbx?
+@end itemize
+
+@node XCOFF Differences
+@appendix Differences Between GNU Stabs in a.out and GNU Stabs in XCOFF
+
+@c FIXME: Merge *all* these into the main body of the document.
+The AIX/RS6000 native object file format is XCOFF with stabs. This
+appendix only covers those differences which are not covered in the main
+body of this document.
+
+@itemize @bullet
+@item
+BSD a.out stab types correspond to AIX XCOFF storage classes. In general
+the mapping is @code{N_@var{stabtype}} becomes @code{C_@var{stabtype}}.
+Some stab types in a.out are not supported in XCOFF; most of these use
+@code{C_DECL}.
+
+@c FIXME: Get C_* types for the block, figure out whether it is always
+@c used (I suspect not), explain clearly, and move to node Statics.
+Exception: initialised static @code{N_STSYM} and un-initialized static
+@code{N_LCSYM} both map to the @code{C_STSYM} storage class. But the
+distinction is preserved because in XCOFF @code{N_STSYM} and
+@code{N_LCSYM} must be emited in a named static block. Begin the block
+with @samp{.bs s[RW] data_section_name} for @code{N_STSYM} or @samp{.bs
+s bss_section_name} for @code{N_LCSYM}. End the block with @samp{.es}.
+
+@c FIXME: I think they are trying to say something about whether the
+@c assembler defaults the value to the location counter.
+@item
+If the XCOFF stab is an @code{N_FUN} (@code{C_FUN}) then follow the
+string field with @samp{,.} instead of just @samp{,}.
+@end itemize
+
+I think that's it for @file{.s} file differences. They could stand to be
+better presented. This is just a list of what I have noticed so far.
+There are a @emph{lot} of differences in the information in the symbol
+tables of the executable and object files.
+
+Mapping of a.out stab types to XCOFF storage classes:
+
+@example
+stab type storage class
+-------------------------------
+N_GSYM C_GSYM
+N_FNAME unused
+N_FUN C_FUN
+N_STSYM C_STSYM
+N_LCSYM C_STSYM
+N_MAIN unknown
+N_PC unknown
+N_RSYM C_RSYM
+unknown C_RPSYM
+N_M2C unknown
+N_SLINE unknown
+N_DSLINE unknown
+N_BSLINE unknown
+N_BROWSE unchanged
+N_CATCH unknown
+N_SSYM unknown
+N_SO unknown
+N_LSYM C_LSYM
+various C_DECL
+N_BINCL unknown
+N_SOL unknown
+N_PSYM C_PSYM
+N_EINCL unknown
+N_ENTRY C_ENTRY
+N_LBRAC unknown
+N_EXCL unknown
+N_SCOPE unknown
+N_RBRAC unknown
+N_BCOMM C_BCOMM
+N_ECOMM C_ECOMM
+N_ECOML C_ECOML
+
+N_LENG unknown
+@end example
+
+@node Sun Differences
+@appendix Differences Between GNU Stabs and Sun Native Stabs
+
+@c FIXME: Merge all this stuff into the main body of the document.
+
+@itemize @bullet
+@item
+GNU C stabs define @emph{all} types, file or procedure scope, as
+@code{N_LSYM}. Sun doc talks about using @code{N_GSYM} too.
+
+@item
+Sun C stabs use type number pairs in the format
+(@var{file-number},@var{type-number}) where @var{file-number} is a
+number starting with 1 and incremented for each sub-source file in the
+compilation. @var{type-number} is a number starting with 1 and
+incremented for each new type defined in the compilation. GNU C stabs
+use the type number alone, with no source file number.
+@end itemize
+
+@node Stabs In ELF
+@appendix Using Stabs With The ELF Object File Format
+
+The ELF object file format allows tools to create object files with
+custom sections containing any arbitrary data. To use stabs in ELF
+object files, the tools create two custom sections, a section named
+@code{.stab} which contains an array of fixed length structures, one
+struct per stab, and a section named @code{.stabstr} containing all the
+variable length strings that are referenced by stabs in the @code{.stab}
+section. The byte order of the stabs binary data matches the byte order
+of the ELF file itself, as determined from the @code{EI_DATA} field in
+the @code{e_ident} member of the ELF header.
+
+The first stab in the @code{.stab} section for each compilation unit is
+synthetic, generated entirely by the assembler, with no corresponding
+@code{.stab} directive as input to the assembler. This stab contains
+the following fields:
+
+@table @code
+@item n_strx
+Offset in the @code{.stabstr} section to the source filename.
+
+@item n_type
+@code{N_UNDF}.
+
+@item n_other
+Unused field, always zero.
+
+@item n_desc
+Count of upcoming symbols, i.e., the number of remaining stabs for this
+source file.
+
+@item n_value
+Size of the string table fragment associated with this source file, in
+bytes.
+@end table
+
+The @code{.stabstr} section always starts with a null byte (so that string
+offsets of zero reference a null string), followed by random length strings,
+each of which is null byte terminated.
+
+The ELF section header for the @code{.stab} section has its
+@code{sh_link} member set to the section number of the @code{.stabstr}
+section, and the @code{.stabstr} section has its ELF section
+header @code{sh_type} member set to @code{SHT_STRTAB} to mark it as a
+string table.
+
+To keep linking fast, it is a bad idea to have the linker relocating
+stabs, so (except for a few cases, see below) none of the addresses in
+the @code{n_value} field of the stabs are relocated by the linker.
+Instead they are relative to the source file (or some entity smaller
+than a source file, like a function). To find the address of each
+section corresponding to a given source file, the compiler puts out
+symbols giving the address of each section for a given source file.
+Since these are ELF (not stab) symbols, the linker relocates them
+correctly without having to touch the stabs section. They are named
+@code{Bbss.bss} for the bss section, @code{Ddata.data} for the data
+section, and @code{Drodata.rodata} for the rodata section. For the text
+section, there is no such symbol (but there should be, see below). For
+an example of how these symbols work, @xref{ELF Transformations}. GCC
+does not provide these symbols; it instead relies on the stabs getting
+relocated, which slows down linking. Thus addresses which would
+normally be relative to @code{Bbss.bss}, etc., are already relocated.
+The Sun linker provided with Solaris 2.2 and earlier relocates stabs
+using normal ELF relocation information, as it would do for any section.
+Sun has been threatening to kludge their linker to not do this (to speed
+up linking), even though the correct way to avoid having the linker do
+these relocations is to have the compiler no longer output relocatable
+values. Last I heard they had been talked out of the linker kludge.
+See Sun point patch 101052-01 and Sun bug 1142109. This affects
+@samp{S} symbol descriptor stabs (@pxref{Statics}) and functions
+(@pxref{Procedures}). In the latter case, to adopt the clean solution
+(making the value of the stab relative to the start of the compilation
+unit), it would be necessary to invent a @code{Ttext.text} symbol,
+analogous to the @code{Bbss.bss}, etc., symbols. I recommend this
+rather than using a zero value and getting the address from the ELF
+symbols.
+
+@node Symbol Types Index
+@unnumbered Symbol Types Index
+
+@printindex fn
+
+@contents
+@bye
diff --git a/gnu/usr.bin/gdb/environ.c b/gnu/usr.bin/gdb/environ.c
deleted file mode 100644
index 022016631331..000000000000
--- a/gnu/usr.bin/gdb/environ.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)environ.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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"
-
-/* 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++);
-
- if (e->allocated < i)
- {
- e->allocated = max (i, e->allocated + 10);
- e->vector = (char **) xrealloc (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]) + 1;
- register char *new = (char *) xmalloc (len);
- bcopy (e->vector[i], new, len);
- 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;
-}
-
-/* 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 (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;
- 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/gnu/usr.bin/gdb/environ.h b/gnu/usr.bin/gdb/environ.h
deleted file mode 100644
index 13f31f470a5e..000000000000
--- a/gnu/usr.bin/gdb/environ.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 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/gnu/usr.bin/gdb/expprint.c b/gnu/usr.bin/gdb/expprint.c
deleted file mode 100644
index 2c63cf8928cb..000000000000
--- a/gnu/usr.bin/gdb/expprint.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/* 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 "param.h"
-#include "symtab.h"
-#include "expression.h"
-#include "value.h"
-
-
-/* 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},
- };
-
-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 int tem;
- register int pc;
- int 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/gnu/usr.bin/gdb/expread.y b/gnu/usr.bin/gdb/expread.y
deleted file mode 100644
index 96a12c48c064..000000000000
--- a/gnu/usr.bin/gdb/expread.y
+++ /dev/null
@@ -1,1782 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-/* Parse C expressions 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. */
-
-/* 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. */
-
-%{
-#ifndef lint
-static char sccsid[] = "@(#)expread.y 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-#include <stdio.h>
-#include "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-#include "expression.h"
-
-#include <a.out.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 ();
-
-/* 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;
- };
-
-/* 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;
- 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> NAME TYPENAME BLOCKNAME STRING
-%type <sval> name name_not_typename typename
-
-%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
-
-/* 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
-
-%%
-
-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 : 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 : 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
- {
- struct symtab *tem = lookup_symtab (copy_name ($1));
- struct symbol *sym;
-
- if (tem)
- $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), 1);
- else
- {
- sym = lookup_symbol (copy_name ($1),
- expression_context_block,
- VAR_NAMESPACE, 0);
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
- $$ = SYMBOL_BLOCK_VALUE (sym);
- else
- error ("No file or function \"%s\".",
- copy_name ($1));
- }
- }
- ;
-
-block : block COLONCOLON name
- { struct symbol *tem
- = lookup_symbol (copy_name ($3), $1, VAR_NAMESPACE, 0);
- 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);
- 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);
- 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 =
- (enum misc_function_type)
- 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 \"symbol-file\" command.");
- else
- error ("No symbol \"%s\" in current context.", name);
- }
- ;
-
-variable: name_not_typename
- { struct symbol *sym;
- int is_a_field_of_this;
-
- sym = lookup_symbol (copy_name ($1),
- expression_context_block,
- VAR_NAMESPACE,
- &is_a_field_of_this);
- if (sym)
- {
- switch (sym->class)
- {
- case LOC_REGISTER:
- case LOC_ARG:
- case LOC_LOCAL:
- 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 (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);
- write_exp_elt_opcode (STRUCTOP_PTR);
- }
- else
- {
- register int i;
- register char *arg = copy_name ($1);
-
- 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 =
- (enum misc_function_type)
- 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 \"symbol-file\" command.");
- else
- error ("No symbol \"%s\" in current context.",
- copy_name ($1));
- }
- }
- ;
-
-
-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
- { $$ = lookup_typename (copy_name ($1),
- expression_context_block, 0); }
- | 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 (copy_name ($2)); }
- | UNSIGNED
- { $$ = builtin_type_unsigned_int; }
- | SIGNED typename
- { $$ = lookup_typename (copy_name ($2),
- expression_context_block, 0); }
- | SIGNED
- { $$ = builtin_type_int; }
- ;
-
-typename: TYPENAME
- | INT_KEYWORD
- {
- $$.ptr = "int";
- $$.length = 3;
- }
- | LONG
- {
- $$.ptr = "long";
- $$.length = 4;
- }
- | SHORT
- {
- $$.ptr = "short";
- $$.length = 5;
- }
- ;
-
-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
- | BLOCKNAME
- | TYPENAME
- ;
-
-name_not_typename : NAME
- | BLOCKNAME
- ;
-
-%%
-
-/* 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);
- }
-}
-
-/* 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);
-}
-
-/* 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 (olen)
- int olen;
-{
- register char *p = lexptr;
- register LONGEST n = 0;
- register int c;
- register int base = 10;
- register int len = olen;
- char *err_copy;
- int unsigned_p = 0;
-
- extern double atof ();
-
- for (c = 0; c < len; c++)
- if (p[c] == '.')
- {
- /* It's a float since it contains a point. */
- yylval.dval = atof (p);
- lexptr += len;
- return FLOAT;
- }
-
- if (len >= 3 && (!strncmp (p, "0x", 2) || !strncmp (p, "0X", 2)))
- {
- p += 2;
- base = 16;
- len -= 2;
- }
- else if (*p == '0')
- base = 8;
-
- 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 += c - '0';
- else
- {
- if (base == 16 && c >= 'a' && c <= 'f')
- n += c - 'a' + 10;
- else if (len == 0 && c == 'l')
- ;
- else if (len == 0 && c == 'u')
- unsigned_p = 1;
- else if (base == 10 && len != 0 && (c == 'e' || c == 'E'))
- {
- /* Scientific notation, where we are unlucky enough not
- to have a '.' in the string. */
- yylval.dval = atof (lexptr);
- lexptr += olen;
- return FLOAT;
- }
- else
- {
- err_copy = (char *) alloca (olen + 1);
- bcopy (lexptr, err_copy, olen);
- err_copy[olen] = 0;
- error ("Invalid number \"%s\".", err_copy);
- }
- }
- }
-
- lexptr = p;
- if (unsigned_p)
- {
- yylval.ulval = n;
- return UINT;
- }
- else
- {
- yylval.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 int 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')
- break; /* Falls into number code. */
-
- case '+':
- case '-':
- case '*':
- case '/':
- case '%':
- case '|':
- case '&':
- case '^':
- case '~':
- case '!':
- case '@':
- case '<':
- case '>':
- case '[':
- case ']':
- case '?':
- case ':':
- case '=':
- case '{':
- case '}':
- 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;
- }
-
- /* Is it a number? */
- /* Note: We have already dealt with the case of the token '.'.
- See case '.' above. */
- if ((c >= '0' && c <= '9') || c == '.')
- {
- /* It's a number. */
- int got_dot = 0, got_e = 0;
- register char *p = tokstart;
- int hex = c == '0' && (p[1] == 'x' || p[1] == 'X');
- if (hex)
- p += 2;
- 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;
- else if (!got_dot && !got_e && (*p=='l'||*p=='L')){
- ++p; break;
- }
- else if (!got_dot && !got_e && !hex && (*p=='u'||*p=='U')){
- ++p; break;
- }
- else if (*p < '0' || *p > '9'
- && (!hex || ((*p < 'a' || *p > 'f')
- && (*p < 'A' || *p > 'F'))))
- break;
- }
- return parse_number (p - tokstart);
- }
-
- 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)
- && lookup_symbol ("$this", expression_context_block,
- VAR_NAMESPACE, 0))
- 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 = (struct internalvar *) 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;
-
- if (lookup_partial_symtab (tmp))
- return BLOCKNAME;
- sym = lookup_symbol (tmp, expression_context_block,
- VAR_NAMESPACE, 0);
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
- return BLOCKNAME;
- if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1))
- return TYPENAME;
- return NAME;
- }
-}
-
-static void
-yyerror ()
-{
- 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;
-}
-
-/* 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;
- }
-}
-
-/* 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;
-{
- 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 ();
- 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/gnu/usr.bin/gdb/findvar.c b/gnu/usr.bin/gdb/findvar.c
deleted file mode 100644
index 0157d101e9a4..000000000000
--- a/gnu/usr.bin/gdb/findvar.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/* 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 "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-#include "value.h"
-
-CORE_ADDR read_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;
-
-#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 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] ?
- saved_regs.regs[regnum] : 0);
- }
-#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;
-}
-
-/* Copy the bytes of register REGNUM, relative to the current stack frame,
- into our memory at MYADDR.
- The number of bytes copied is REGISTER_RAW_SIZE (REGNUM). */
-
-void
-read_relative_register_raw_bytes (regnum, myaddr)
- int regnum;
- char *myaddr;
-{
- register CORE_ADDR addr;
-
- if (regnum == FP_REGNUM)
- {
- bcopy (&FRAME_FP(selected_frame), myaddr, sizeof (CORE_ADDR));
- return;
- }
-
- addr = find_saved_register (selected_frame, regnum);
-
- if (addr)
- {
- if (regnum == SP_REGNUM)
- {
- CORE_ADDR buffer = addr;
- bcopy (&buffer, myaddr, sizeof (CORE_ADDR));
- }
- else
- read_memory (addr, myaddr, REGISTER_RAW_SIZE (regnum));
- return;
- }
- read_register_bytes (REGISTER_BYTE (regnum),
- myaddr, REGISTER_RAW_SIZE (regnum));
-}
-
-/* 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;
-{
- register CORE_ADDR addr;
- register value val;
- char raw_buffer[MAX_REGISTER_RAW_SIZE];
- char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
-
- if (! (have_inferior_p () || have_core_file_p ()))
- error ("Can't get value of register without inferior or core file");
-
- addr = find_saved_register (selected_frame, regnum);
- if (addr)
- {
- if (regnum == SP_REGNUM)
- return value_from_long (builtin_type_int, (LONGEST) addr);
- read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
- }
- else
- read_register_bytes (REGISTER_BYTE (regnum), raw_buffer,
- REGISTER_RAW_SIZE (regnum));
-
- REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer);
- val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
- bcopy (virtual_buffer, VALUE_CONTENTS (val), REGISTER_VIRTUAL_SIZE (regnum));
- VALUE_LVAL (val) = addr ? lval_memory : lval_register;
- VALUE_ADDRESS (val) = addr ? addr : REGISTER_BYTE (regnum);
- VALUE_REGNO (val) = regnum;
- return val;
-}
-
-/* Low level examining and depositing of registers.
-
- Note that you must call `fetch_registers' once
- before examining or depositing any registers. */
-
-char registers[REGISTER_BYTES];
-
-/* 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;
-{
- bcopy (&registers[regbyte], myaddr, len);
-}
-
-/* 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;
-{
- bcopy (myaddr, &registers[regbyte], len);
- if (have_inferior_p ())
- store_inferior_registers (-1);
-}
-
-/* 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) */
-#if defined(sun4)
- /* This is a no-op on a Sun 4. */
- if (regno == 0)
- return;
-#endif
-
- *(int *) &registers[REGISTER_BYTE (regno)] = val;
-
- if (have_inferior_p ())
- store_inferior_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;
-{
- bcopy (val, &registers[REGISTER_BYTE (regno)], REGISTER_RAW_SIZE (regno));
-}
-
-/* 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. */
-
-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);
- register CORE_ADDR addr = 0;
- int val = SYMBOL_VALUE (var);
- 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:
- case LOC_LABEL:
- bcopy (&val, VALUE_CONTENTS (v), len);
- VALUE_LVAL (v) = not_lval;
- return v;
-
- case LOC_CONST_BYTES:
- bcopy (val, VALUE_CONTENTS (v), len);
- VALUE_LVAL (v) = not_lval;
- return v;
-
- case LOC_STATIC:
- addr = val;
- 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 = val + FRAME_ARGS_ADDRESS (fi);
- break;
-
- case LOC_REF_ARG:
- fi = get_frame_info (frame);
- addr = val + FRAME_ARGS_ADDRESS (fi);
- addr = read_memory_integer (addr, sizeof (CORE_ADDR));
- break;
-
- case LOC_LOCAL:
- fi = get_frame_info (frame);
- addr = val + FRAME_LOCALS_ADDRESS (fi);
- break;
-
- case LOC_TYPEDEF:
- error ("Cannot look up value of a typedef");
-
- 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, val, 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;
- }
- }
-
- read_memory (addr, VALUE_CONTENTS (v), len);
- VALUE_ADDRESS (v) = addr;
- 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;
- value v = allocate_value (type);
- int len = TYPE_LENGTH (type);
- char *value_bytes = 0;
- int value_bytes_copied = 0;
- int num_storage_locs;
-
- 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;
-
- 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))
- {
- int register_index = local_regnum - regnum;
- addr = find_saved_register (frame, local_regnum);
- if (addr == 0)
- {
- read_register_bytes (REGISTER_BYTE (local_regnum),
- value_bytes + value_bytes_copied,
- REGISTER_RAW_SIZE (local_regnum));
- reg_stor++;
- }
- else
- {
- read_memory (addr, value_bytes + value_bytes_copied,
- REGISTER_RAW_SIZE (local_regnum));
- mem_stor++;
- 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) = find_saved_register (frame, regnum);
- }
- else if (reg_stor)
- {
- VALUE_LVAL (v) = lval_register;
- VALUE_ADDRESS (v) = REGISTER_BYTE (regnum);
- }
- else
- fatal ("value_from_register: Value not stored anywhere!");
-
- /* Any structure stored in more than one register will always be
- an inegral 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 (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. */
-
- addr = find_saved_register (frame, regnum);
- if (addr == 0)
- {
- /* Value is really in a register. */
-
- VALUE_LVAL (v) = lval_register;
- VALUE_ADDRESS (v) = REGISTER_BYTE (regnum);
-
- read_register_bytes (REGISTER_BYTE (regnum),
- raw_buffer, REGISTER_RAW_SIZE (regnum));
- }
- else
- {
- /* Value was in a register that has been saved in memory. */
-
- read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
- VALUE_LVAL (v) = lval_memory;
- VALUE_ADDRESS (v) = addr;
- }
-
- /* Convert the raw contents to virtual contents.
- (Just copy them if the formats are the same.) */
-
- REGISTER_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 (v), len);
- v = value_cast (type, v);
- }
- else
- bcopy (virtual_buffer, VALUE_CONTENTS (v), len);
- }
- else
- {
- /* Raw and virtual formats are the same for this register. */
-
-#ifdef BYTES_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 (v), len);
- }
-
- return v;
-}
-
-/* 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;
-{
- register CORE_ADDR addr = 0;
- int val = SYMBOL_VALUE (var);
- struct frame_info *fi;
- struct type *type = SYMBOL_TYPE (var);
- struct type *result_type;
-
- if (frame == 0) frame = selected_frame;
-
- switch (SYMBOL_CLASS (var))
- {
- case LOC_CONST:
- case LOC_CONST_BYTES:
- error ("Address requested for identifier \"%s\" which is a constant.",
- SYMBOL_NAME (var));
-
- case LOC_REGISTER:
- case LOC_REGPARM:
- addr = find_saved_register (frame, val);
- if (addr != 0)
- {
- int len = TYPE_LENGTH (type);
-#ifdef BYTES_BIG_ENDIAN
- if (len < REGISTER_RAW_SIZE (val))
- /* Big-endian, and we want less than full size. */
- addr += REGISTER_RAW_SIZE (val) - len;
-#endif
- break;
- }
- error ("Address requested for identifier \"%s\" which is in a register.",
- SYMBOL_NAME (var));
-
- case LOC_STATIC:
- case LOC_LABEL:
- addr = val;
- break;
-
- case LOC_ARG:
- fi = get_frame_info (frame);
- addr = val + FRAME_ARGS_ADDRESS (fi);
- break;
-
- case LOC_REF_ARG:
- fi = get_frame_info (frame);
- addr = val + FRAME_ARGS_ADDRESS (fi);
- addr = read_memory_integer (addr, sizeof (CORE_ADDR));
- break;
-
- case LOC_LOCAL:
- fi = get_frame_info (frame);
- addr = val + FRAME_LOCALS_ADDRESS (fi);
- break;
-
- case LOC_TYPEDEF:
- error ("Address requested for identifier \"%s\" which is a typedef.",
- SYMBOL_NAME (var));
-
- case LOC_BLOCK:
- addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
- break;
- }
-
- /* 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));
-}
-
diff --git a/gnu/usr.bin/gdb/frame.h b/gnu/usr.bin/gdb/frame.h
deleted file mode 100644
index 322ddbae04b9..000000000000
--- a/gnu/usr.bin/gdb/frame.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* 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. */
-
-/* Note that frame.h requires 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 get_frame_saved_regs ();
-
-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 struct symbol *get_pc_function ();
-
-/* In stack.c */
-extern FRAME find_relative_frame ();
-
-/* Generic pointer value indicating "I don't know." */
-#define Frame_unknown (CORE_ADDR)-1
diff --git a/gnu/usr.bin/gdb/gdb.1 b/gnu/usr.bin/gdb/gdb.1
deleted file mode 100644
index 57d744b29368..000000000000
--- a/gnu/usr.bin/gdb/gdb.1
+++ /dev/null
@@ -1,3 +0,0 @@
-.\" %W% (Berkeley) %G%
-.\"
-.\" placeholder, until we can produce the manual page
diff --git a/gnu/usr.bin/gdb/gdb/COPYING b/gnu/usr.bin/gdb/gdb/COPYING
new file mode 100644
index 000000000000..a43ea2126fb6
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 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 licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU 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. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), 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 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 show them these terms so they know 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.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License 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 derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 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 License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+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.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary 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
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 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 Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing 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 for copying, distributing or modifying
+the Program or works based on it.
+
+ 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.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. 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 this 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
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. 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
+
+ 11. 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.
+
+ 12. 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
+
+ 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 the public, 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 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 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) 19yy 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 is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/gdb/gdb/Makefile b/gnu/usr.bin/gdb/gdb/Makefile
new file mode 100644
index 000000000000..2fac3dbd1c1d
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/Makefile
@@ -0,0 +1,72 @@
+PROG = gdb
+BINDIR= /usr/bin
+SRCS = main.c blockframe.c breakpoint.c findvar.c stack.c thread.c \
+ source.c values.c eval.c valops.c valarith.c valprint.c printcmd.c \
+ symtab.c symfile.c symmisc.c infcmd.c infrun.c command.c utils.c \
+ expprint.c environ.c gdbtypes.c copying.c i386-tdep.c i386-pinsn.c \
+ freebsd-solib.c ser-unix.c exec.c fork-child.c infptrace.c inftarg.c \
+ corelow.c coredep.c freebsd-nat.c remote.c dcache.c remote-utils.c \
+ mem-break.c target.c putenv.c parse.c language.c buildsym.c \
+ objfiles.c minsyms.c maint.c demangle.c dbxread.c coffread.c \
+ elfread.c dwarfread.c mipsread.c stabsread.c core.c c-lang.c \
+ ch-lang.c m2-lang.c complaints.c typeprint.c c-typeprint.c \
+ ch-typeprint.c m2-typeprint.c c-valprint.c cp-valprint.c ch-valprint.c \
+ m2-valprint.c nlmread.c serial.c inflow.c regex.c init.c \
+ c-exp.tab.c ch-exp.tab.c m2-exp.tab.c version.c i386-dis.c dis-buf.c
+
+c-exp.tab.c: $(.CURDIR)/c-exp.y
+ yacc -d -p c_ $(.CURDIR)/c-exp.y
+ sed -e '/extern.*malloc/d' -e '/extern.*realloc/d' -e '/extern.*free/d' \
+ -e '/include.*malloc.h/d' -e 's/malloc/xmalloc/g' \
+ -e 's/realloc/xrealloc/g' < y.tab.c > c-exp.new
+ rm y.tab.c
+ mv c-exp.new ./c-exp.tab.c
+
+ch-exp.tab.c: $(.CURDIR)/ch-exp.y
+ yacc -d -p ch_ $(.CURDIR)/ch-exp.y
+ sed -e '/extern.*malloc/d' -e '/extern.*realloc/d' -e '/extern.*free/d' \
+ -e '/include.*malloc.h/d' -e 's/malloc/xmalloc/g' \
+ -e 's/realloc/xrealloc/g' < y.tab.c > ch-exp.new
+ rm y.tab.c
+ mv ch-exp.new ./ch-exp.tab.c
+
+m2-exp.tab.c: $(.CURDIR)/m2-exp.y
+ yacc -d -p m2_ $(.CURDIR)/m2-exp.y
+ sed -e '/extern.*malloc/d' -e '/extern.*realloc/d' -e '/extern.*free/d' \
+ -e '/include.*malloc.h/d' -e 's/malloc/xmalloc/g' \
+ -e 's/realloc/xrealloc/g' < y.tab.c > m2-exp.new
+ rm y.tab.c
+ mv m2-exp.new ./m2-exp.tab.c
+
+
+
+CFLAGS+= -I$(.CURDIR)/. -I/usr/include/readline -I$(.CURDIR)/../bfd
+DPADD+= $(LIBREADLINE) $(LIBTERM)
+LDADD+= -lreadline -ltermcap
+
+.if exists(${.CURDIR}/../libiberty/obj)
+LDADD+= -L${.CURDIR}/../libiberty/obj -liberty
+DPADD+= ${.CURDIR}/../libiberty/obj/libiberty.a
+.else
+LDADD+= -L${.CURDIR}/../libiberty/ -liberty
+DPADD+= ${.CURDIR}/../libiberty/libiberty.a
+.endif
+
+.if exists(${.CURDIR}/../bfd/obj)
+LDADD+= -L${.CURDIR}/../bfd/obj -lbfd
+DPADD+= ${.CURDIR}/../bfd/obj/libbfd.a
+.else
+LDADD+= -L${.CURDIR}/../bfd/ -lbfd
+DPADD+= ${.CURDIR}/../bfd/libbfd.a
+.endif
+
+.if exists(${.CURDIR}/../mmalloc/obj)
+LDADD+= -L${.CURDIR}/../mmalloc/obj -lmmalloc
+DPADD+= ${.CURDIR}/../mmalloc/obj/libmmalloc.a
+.else
+LDADD+= -L${.CURDIR}/../mmalloc/ -lmmalloc
+DPADD+= ${.CURDIR}/../mmalloc/libmmalloc.a
+.endif
+
+
+.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/gdb/gdb/ansidecl.h b/gnu/usr.bin/gdb/gdb/ansidecl.h
new file mode 100644
index 000000000000..fdc4072120ed
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/ansidecl.h
@@ -0,0 +1,139 @@
+/* ANSI and traditional C compatability macros
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macro ANSI C definition Traditional C definition
+ ----- ---- - ---------- ----------- - ----------
+ PTR `void *' `char *'
+ LONG_DOUBLE `long double' `double'
+ VOLATILE `volatile' `'
+ SIGNED `signed' `'
+ PTRCONST `void *const' `char *'
+
+ CONST is also defined, but is obsolete. Just use const.
+
+ DEFUN (name, arglist, args)
+
+ Defines function NAME.
+
+ ARGLIST lists the arguments, separated by commas and enclosed in
+ parentheses. ARGLIST becomes the argument list in traditional C.
+
+ ARGS list the arguments with their types. It becomes a prototype in
+ ANSI C, and the type declarations in traditional C. Arguments should
+ be separated with `AND'. For functions with a variable number of
+ arguments, the last thing listed should be `DOTS'.
+
+ DEFUN_VOID (name)
+
+ Defines a function NAME, which takes no arguments.
+
+ obsolete -- EXFUN (name, (prototype)) -- obsolete.
+
+ Replaced by PARAMS. Do not use; will disappear someday soon.
+ Was used in external function declarations.
+ In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+ parentheses). In traditional C it is `NAME()'.
+ For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+ PARAMS ((args))
+
+ We could use the EXFUN macro to handle prototype declarations, but
+ the name is misleading and the result is ugly. So we just define a
+ simple macro to handle the parameter lists, as in:
+
+ static int foo PARAMS ((int, char));
+
+ This produces: `static int foo();' or `static int foo (int, char);'
+
+ EXFUN would have done it like this:
+
+ static int EXFUN (foo, (int, char));
+
+ but the function is not external...and it's hard to visually parse
+ the function name out of the mess. EXFUN should be considered
+ obsolete; new code should be written to use PARAMS.
+
+ For example:
+ extern int printf PARAMS ((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 */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4))
+/* All known AIX compilers implement these things (but don't always
+ define __STDC__). The RISC/OS MIPS compiler defines these things
+ in SVR4 mode, but does not define __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(void)
+
+#define PROTO(type, name, arglist) type name arglist
+#define PARAMS(paramlist) paramlist
+
+#else /* Not ANSI C. */
+
+#define PTR char *
+#define PTRCONST PTR
+#define LONG_DOUBLE double
+
+#define AND ;
+#define NOARGS
+#define CONST
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define const
+#endif
+#define VOLATILE
+#define SIGNED
+#define DOTS
+
+#define EXFUN(name, proto) name()
+#define DEFUN(name, arglist, args) name arglist args;
+#define DEFUN_VOID(name) name()
+#define PROTO(type, name, arglist) type name ()
+#define PARAMS(paramlist) ()
+
+#endif /* ANSI C. */
+
+#endif /* ansidecl.h */
diff --git a/gnu/usr.bin/gdb/gdb/aout/aout64.h b/gnu/usr.bin/gdb/gdb/aout/aout64.h
new file mode 100644
index 000000000000..018e6ddb0685
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/aout/aout64.h
@@ -0,0 +1,431 @@
+/* `a.out' object-file definitions, including extensions to 64-bit fields */
+
+#ifndef __A_OUT_64_H__
+#define __A_OUT_64_H__
+
+/* This is the layout on disk of the 32-bit or 64-bit exec header. */
+
+#ifndef external_exec
+struct external_exec
+{
+ bfd_byte e_info[4]; /* magic number and stuff */
+ bfd_byte e_text[BYTES_IN_WORD]; /* length of text section in bytes */
+ bfd_byte e_data[BYTES_IN_WORD]; /* length of data section in bytes */
+ bfd_byte e_bss[BYTES_IN_WORD]; /* length of bss area in bytes */
+ bfd_byte e_syms[BYTES_IN_WORD]; /* length of symbol table in bytes */
+ bfd_byte e_entry[BYTES_IN_WORD]; /* start address */
+ bfd_byte e_trsize[BYTES_IN_WORD]; /* length of text relocation info */
+ bfd_byte e_drsize[BYTES_IN_WORD]; /* length of data relocation info */
+};
+
+#define EXEC_BYTES_SIZE (4 + BYTES_IN_WORD * 7)
+
+/* Magic numbers for a.out files */
+
+#if ARCH_SIZE==64
+#define OMAGIC 0x1001 /* Code indicating object file */
+#define ZMAGIC 0x1002 /* Code indicating demand-paged executable. */
+#define NMAGIC 0x1003 /* Code indicating pure executable. */
+
+/* There is no 64-bit QMAGIC as far as I know. */
+
+#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+#else
+#define OMAGIC 0407 /* ...object file or impure executable. */
+#define NMAGIC 0410 /* Code indicating pure executable. */
+#define ZMAGIC 0413 /* Code indicating demand-paged executable. */
+
+/* This indicates a demand-paged executable with the header in the text.
+ As far as I know it is only used by 386BSD and/or BSDI. */
+#define QMAGIC 0314
+# ifndef N_BADMAG
+# define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC \
+ && N_MAGIC(x) != QMAGIC)
+# endif /* N_BADMAG */
+#endif
+
+#endif
+
+#ifdef QMAGIC
+#define N_IS_QMAGIC(x) (N_MAGIC (x) == QMAGIC)
+#else
+#define N_IS_QMAGIC(x) (0)
+#endif
+
+/* The difference between PAGE_SIZE and N_SEGSIZE is that PAGE_SIZE is
+ the the finest granularity at which you can page something, thus it
+ controls the padding (if any) before the text segment of a ZMAGIC
+ file. N_SEGSIZE is the resolution at which things can be marked as
+ read-only versus read/write, so it controls the padding between the
+ text segment and the data segment (in memory; on disk the padding
+ between them is PAGE_SIZE). PAGE_SIZE and N_SEGSIZE are the same
+ for most machines, but different for sun3. */
+
+/* By default, segment size is constant. But some machines override this
+ to be a function of the a.out header (e.g. machine type). */
+
+#ifndef N_SEGSIZE
+#define N_SEGSIZE(x) SEGMENT_SIZE
+#endif
+
+/* Virtual memory address of the text section.
+ This is getting very complicated. A good reason to discard a.out format
+ for something that specifies these fields explicitly. But til then...
+
+ * OMAGIC and NMAGIC files:
+ (object files: text for "relocatable addr 0" right after the header)
+ start at 0, offset is EXEC_BYTES_SIZE, size as stated.
+ * The text address, offset, and size of ZMAGIC files depend
+ on the entry point of the file:
+ * entry point below TEXT_START_ADDR:
+ (hack for SunOS shared libraries)
+ start at 0, offset is 0, size as stated.
+ * If N_HEADER_IN_TEXT(x) is true (which defaults to being the
+ case when the entry point is EXEC_BYTES_SIZE or further into a page):
+ no padding is needed; text can start after exec header. Sun
+ considers the text segment of such files to include the exec header;
+ for BFD's purposes, we don't, which makes more work for us.
+ start at TEXT_START_ADDR + EXEC_BYTES_SIZE, offset is EXEC_BYTES_SIZE,
+ size as stated minus EXEC_BYTES_SIZE.
+ * If N_HEADER_IN_TEXT(x) is false (which defaults to being the case when
+ the entry point is less than EXEC_BYTES_SIZE into a page (e.g. page
+ aligned)): (padding is needed so that text can start at a page boundary)
+ start at TEXT_START_ADDR, offset PAGE_SIZE, size as stated.
+
+ Specific configurations may want to hardwire N_HEADER_IN_TEXT,
+ for efficiency or to allow people to play games with the entry point.
+ In that case, you would #define N_HEADER_IN_TEXT(x) as 1 for sunos,
+ and as 0 for most other hosts (Sony News, Vax Ultrix, etc).
+ (Do this in the appropriate bfd target file.)
+ (The default is a heuristic that will break if people try changing
+ the entry point, perhaps with the ld -e flag.)
+
+ * QMAGIC is always like a ZMAGIC for which N_HEADER_IN_TEXT is true,
+ and for which the starting address is PAGE_SIZE (or should this be
+ SEGMENT_SIZE?) (TEXT_START_ADDR only applies to ZMAGIC, not to QMAGIC).
+ */
+
+/* This macro is only relevant for ZMAGIC files; QMAGIC always has the header
+ in the text. */
+#ifndef N_HEADER_IN_TEXT
+#define N_HEADER_IN_TEXT(x) (((x).a_entry & (PAGE_SIZE-1)) >= EXEC_BYTES_SIZE)
+#endif
+
+/* Sun shared libraries, not linux. This macro is only relevant for ZMAGIC
+ files. */
+#ifndef N_SHARED_LIB
+#define N_SHARED_LIB(x) ((x).a_entry < TEXT_START_ADDR)
+#endif
+
+#ifndef N_TXTADDR
+#define N_TXTADDR(x) \
+ (/* The address of a QMAGIC file is always one page in, */ \
+ /* with the header in the text. */ \
+ N_IS_QMAGIC (x) ? PAGE_SIZE + EXEC_BYTES_SIZE : \
+ N_MAGIC(x) != ZMAGIC ? 0 : /* object file or NMAGIC */\
+ N_SHARED_LIB(x) ? 0 : \
+ N_HEADER_IN_TEXT(x) ? \
+ TEXT_START_ADDR + EXEC_BYTES_SIZE : /* no padding */\
+ TEXT_START_ADDR /* a page of padding */\
+ )
+#endif
+
+/* Offset in an a.out of the start of the text section. */
+#ifndef N_TXTOFF
+#define N_TXTOFF(x) \
+ (/* For {O,N,Q}MAGIC, no padding. */ \
+ N_MAGIC(x) != ZMAGIC ? EXEC_BYTES_SIZE : \
+ N_SHARED_LIB(x) ? 0 : \
+ N_HEADER_IN_TEXT(x) ? \
+ EXEC_BYTES_SIZE : /* no padding */\
+ PAGE_SIZE /* a page of padding */\
+ )
+#endif
+/* Size of the text section. It's always as stated, except that we
+ offset it to `undo' the adjustment to N_TXTADDR and N_TXTOFF
+ for ZMAGIC files that nominally include the exec header
+ as part of the first page of text. (BFD doesn't consider the
+ exec header to be part of the text segment.) */
+#ifndef N_TXTSIZE
+#define N_TXTSIZE(x) \
+ (/* For QMAGIC, we don't consider the header part of the text section. */\
+ N_IS_QMAGIC (x) ? (x).a_text - EXEC_BYTES_SIZE : \
+ (N_MAGIC(x) != ZMAGIC || N_SHARED_LIB(x)) ? (x).a_text : \
+ N_HEADER_IN_TEXT(x) ? \
+ (x).a_text - EXEC_BYTES_SIZE: /* no padding */\
+ (x).a_text /* a page of padding */\
+ )
+#endif
+/* The address of the data segment in virtual memory.
+ It is the text segment address, plus text segment size, rounded
+ up to a N_SEGSIZE boundary for pure or pageable files. */
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+N_TXTSIZE(x)) \
+ : (N_SEGSIZE(x) + ((N_TXTADDR(x)+N_TXTSIZE(x)-1) & ~(N_SEGSIZE(x)-1))))
+#endif
+/* The address of the BSS segment -- immediately after the data segment. */
+
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+
+/* Offsets of the various portions of the file after the text segment. */
+
+/* For {N,Q,Z}MAGIC, there is padding to make the data segment start
+ on a page boundary. Most of the time the a_text field (and thus
+ N_TXTSIZE) already contains this padding. But if it doesn't (I
+ think maybe this happens on BSDI and/or 386BSD), then add it. */
+
+#ifndef N_DATOFF
+#define N_DATOFF(x) \
+ (N_MAGIC(x) == OMAGIC ? N_TXTOFF(x) + N_TXTSIZE(x) : \
+ PAGE_SIZE + ((N_TXTOFF(x) + N_TXTSIZE(x) - 1) & ~(PAGE_SIZE - 1)))
+#endif
+
+#ifndef N_TRELOFF
+#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data )
+#endif
+#ifndef N_DRELOFF
+#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize )
+#endif
+#ifndef N_SYMOFF
+#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize )
+#endif
+#ifndef N_STROFF
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+#endif
+
+/* Symbols */
+#ifndef external_nlist
+struct external_nlist {
+ bfd_byte e_strx[BYTES_IN_WORD]; /* index into string table of name */
+ bfd_byte e_type[1]; /* type of symbol */
+ bfd_byte e_other[1]; /* misc info (usually empty) */
+ bfd_byte e_desc[2]; /* description field */
+ bfd_byte e_value[BYTES_IN_WORD]; /* value of symbol */
+};
+#define EXTERNAL_NLIST_SIZE (BYTES_IN_WORD+4+BYTES_IN_WORD)
+#endif
+
+struct internal_nlist {
+ unsigned long n_strx; /* index into string table of name */
+ unsigned char n_type; /* type of symbol */
+ unsigned char n_other; /* misc info (usually empty) */
+ unsigned short n_desc; /* description field */
+ bfd_vma n_value; /* value of symbol */
+};
+
+/* The n_type field is the symbol type, containing: */
+
+#define N_UNDF 0 /* Undefined symbol */
+#define N_ABS 2 /* Absolute symbol -- defined at particular addr */
+#define N_TEXT 4 /* Text sym -- defined at offset in text seg */
+#define N_DATA 6 /* Data sym -- defined at offset in data seg */
+#define N_BSS 8 /* BSS sym -- defined at offset in zero'd seg */
+#define N_COMM 0x12 /* Common symbol (visible after shared lib dynlink) */
+#define N_FN 0x1f /* File name of .o file */
+#define N_FN_SEQ 0x0C /* N_FN from Sequent compilers (sigh) */
+/* Note: N_EXT can only be usefully OR-ed with N_UNDF, N_ABS, N_TEXT,
+ N_DATA, or N_BSS. When the low-order bit of other types is set,
+ (e.g. N_WARNING versus N_FN), they are two different types. */
+#define N_EXT 1 /* External symbol (as opposed to local-to-this-file) */
+#define N_TYPE 0x1e
+#define N_STAB 0xe0 /* If any of these bits are on, it's a debug symbol */
+
+#define N_INDR 0x0a
+
+/* 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
+ elements 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. */
+
+/* Warning symbol. The text gives a warning message, the next symbol
+ in the table will be undefined. When the symbol is referenced, the
+ message is printed. */
+
+#define N_WARNING 0x1e
+
+/* Relocations
+
+ There are two types of relocation flavours for a.out systems,
+ standard and extended. The standard form is used on systems where the
+ instruction has room for all the bits of an offset to the operand, whilst
+ the extended form is used when an address operand has to be split over n
+ instructions. Eg, on the 68k, each move instruction can reference
+ the target with a displacement of 16 or 32 bits. On the sparc, move
+ instructions use an offset of 14 bits, so the offset is stored in
+ the reloc field, and the data in the section is ignored.
+*/
+
+/* 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. */
+
+struct reloc_std_external {
+ bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
+ bfd_byte r_index[3]; /* symbol table index of symbol */
+ bfd_byte r_type[1]; /* relocation type */
+};
+
+#define RELOC_STD_BITS_PCREL_BIG 0x80
+#define RELOC_STD_BITS_PCREL_LITTLE 0x01
+
+#define RELOC_STD_BITS_LENGTH_BIG 0x60
+#define RELOC_STD_BITS_LENGTH_SH_BIG 5 /* To shift to units place */
+#define RELOC_STD_BITS_LENGTH_LITTLE 0x06
+#define RELOC_STD_BITS_LENGTH_SH_LITTLE 1
+
+#define RELOC_STD_BITS_EXTERN_BIG 0x10
+#define RELOC_STD_BITS_EXTERN_LITTLE 0x08
+
+#define RELOC_STD_BITS_BASEREL_BIG 0x08
+#define RELOC_STD_BITS_BASEREL_LITTLE 0x08
+
+#define RELOC_STD_BITS_JMPTABLE_BIG 0x04
+#define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04
+
+#define RELOC_STD_BITS_RELATIVE_BIG 0x02
+#define RELOC_STD_BITS_RELATIVE_LITTLE 0x02
+
+#define RELOC_STD_SIZE (BYTES_IN_WORD + 3 + 1) /* Bytes per relocation entry */
+
+struct reloc_std_internal
+{
+ bfd_vma r_address; /* Address (within segment) to be relocated. */
+ /* 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 files 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;
+ /* The next three bits are for SunOS shared libraries, and seem to
+ be undocumented. */
+ unsigned int r_baserel:1; /* Linkage table relative */
+ unsigned int r_jmptable:1; /* pc-relative to jump table */
+ unsigned int r_relative:1; /* "relative relocation" */
+ /* unused */
+ unsigned int r_pad:1; /* Padding -- set to zero */
+};
+
+
+/* EXTENDED RELOCS */
+
+struct reloc_ext_external {
+ bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
+ bfd_byte r_index[3]; /* symbol table index of symbol */
+ bfd_byte r_type[1]; /* relocation type */
+ bfd_byte r_addend[BYTES_IN_WORD]; /* datum addend */
+};
+
+#define RELOC_EXT_BITS_EXTERN_BIG 0x80
+#define RELOC_EXT_BITS_EXTERN_LITTLE 0x01
+
+#define RELOC_EXT_BITS_TYPE_BIG 0x1F
+#define RELOC_EXT_BITS_TYPE_SH_BIG 0
+#define RELOC_EXT_BITS_TYPE_LITTLE 0xF8
+#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3
+
+/* Bytes per relocation entry */
+#define RELOC_EXT_SIZE (BYTES_IN_WORD + 3 + 1 + BYTES_IN_WORD)
+
+enum reloc_type
+{
+ /* simple relocations */
+ RELOC_8, /* data[0:7] = addend + sv */
+ RELOC_16, /* data[0:15] = addend + sv */
+ RELOC_32, /* data[0:31] = addend + sv */
+ /* pc-rel displacement */
+ RELOC_DISP8, /* data[0:7] = addend - pc + sv */
+ RELOC_DISP16, /* data[0:15] = addend - pc + sv */
+ RELOC_DISP32, /* data[0:31] = addend - pc + sv */
+ /* Special */
+ RELOC_WDISP30, /* data[0:29] = (addend + sv - pc)>>2 */
+ RELOC_WDISP22, /* data[0:21] = (addend + sv - pc)>>2 */
+ RELOC_HI22, /* data[0:21] = (addend + sv)>>10 */
+ RELOC_22, /* data[0:21] = (addend + sv) */
+ RELOC_13, /* data[0:12] = (addend + sv) */
+ RELOC_LO10, /* data[0:9] = (addend + sv) */
+ RELOC_SFA_BASE,
+ RELOC_SFA_OFF13,
+ /* P.I.C. (base-relative) */
+ RELOC_BASE10, /* Not sure - maybe we can do this the */
+ RELOC_BASE13, /* right way now */
+ RELOC_BASE22,
+ /* for some sort of pc-rel P.I.C. (?) */
+ RELOC_PC10,
+ RELOC_PC22,
+ /* P.I.C. jump table */
+ RELOC_JMP_TBL,
+ /* reputedly for shared libraries somehow */
+ RELOC_SEGOFF16,
+ RELOC_GLOB_DAT,
+ RELOC_JMP_SLOT,
+ RELOC_RELATIVE,
+
+ RELOC_11,
+ RELOC_WDISP2_14,
+ RELOC_WDISP19,
+ RELOC_HHI22, /* data[0:21] = (addend + sv) >> 42 */
+ RELOC_HLO10, /* data[0:9] = (addend + sv) >> 32 */
+
+ /* 29K relocation types */
+ RELOC_JUMPTARG,
+ RELOC_CONST,
+ RELOC_CONSTH,
+
+
+ /* Q .
+ What are the other ones,
+ Since this is a clean slate, can we throw away the ones we dont
+ understand ? Should we sort the values ? What about using a
+ microcode format like the 68k ?
+ */
+ NO_RELOC
+ };
+
+
+struct reloc_internal {
+ bfd_vma r_address; /* offset of of data to relocate */
+ long r_index; /* symbol table index of symbol */
+ enum reloc_type r_type; /* relocation type */
+ bfd_vma r_addend; /* datum addend */
+};
+
+/* Q.
+ Should the length of the string table be 4 bytes or 8 bytes ?
+
+ Q.
+ What about archive indexes ?
+
+ */
+
+#endif /* __A_OUT_64_H__ */
diff --git a/gnu/usr.bin/gdb/gdb/aout/ar.h b/gnu/usr.bin/gdb/gdb/aout/ar.h
new file mode 100644
index 000000000000..cca636d81936
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/aout/ar.h
@@ -0,0 +1,32 @@
+/* archive file definition for GNU software */
+
+/* So far this is correct for BSDish archives. Don't forget that
+ files must begin on an even byte boundary. */
+
+#ifndef __GNU_AR_H__
+#define __GNU_AR_H__
+
+#define ARMAG "!<arch>\n" /* For COFF and a.out archives */
+#define ARMAGB "!<bout>\n" /* For b.out archives */
+#define SARMAG 8
+#define ARFMAG "`\n"
+
+/* The ar_date field of the armap (__.SYMDEF) member of an archive
+ must be greater than the modified date of the entire file, or
+ BSD-derived linkers complain. We originally write the ar_date with
+ this offset from the real file's mod-time. After finishing the
+ file, we rewrite ar_date if it's not still greater than the mod date. */
+
+#define ARMAP_TIME_OFFSET 60
+
+struct ar_hdr {
+ char ar_name[16]; /* name of this member */
+ char ar_date[12]; /* file mtime */
+ char ar_uid[6]; /* owner uid; printed as decimal */
+ char ar_gid[6]; /* owner gid; printed as decimal */
+ char ar_mode[8]; /* file mode, printed as octal */
+ char ar_size[10]; /* file size, printed as decimal */
+ char ar_fmag[2]; /* should contain ARFMAG */
+};
+
+#endif /* __GNU_AR_H__ */
diff --git a/gnu/usr.bin/gdb/gdb/aout/ranlib.h b/gnu/usr.bin/gdb/gdb/aout/ranlib.h
new file mode 100644
index 000000000000..53e35ce2e0e7
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/aout/ranlib.h
@@ -0,0 +1,62 @@
+/* ranlib.h -- archive library index member definition for GNU.
+ Copyright 1990-1991 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 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 */
+
+#define RANLIBMAG "__.SYMDEF" /* Archive file name containing index */
+#define RANLIBSKEW 3 /* Creation time offset */
+
+/* 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;
+ /* this points to the front of the file header (AKA member header --
+ a struct ar_hdr), not to the front of the file or into the file).
+ in other words it only tells you which file to read */
+ unsigned long file_offset;
+ };
+
+/* Compatability with BSD code */
+
+#define ranlib symdef
+#define ran_un s
+#define ran_strx string_offset
+#define ran_name name
+#define ran_off file_offset
diff --git a/gnu/usr.bin/gdb/gdb/aout/stab.def b/gnu/usr.bin/gdb/gdb/aout/stab.def
new file mode 100644
index 000000000000..9d1da7d6eb8f
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/aout/stab.def
@@ -0,0 +1,264 @@
+/* Table of DBX symbol codes for the GNU system.
+ Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* New stab from Solaris 2. This uses an n_type of 0, which in a.out files
+ overlaps the N_UNDF used for ordinary symbols. In ELF files, the
+ debug information is in a different file section, so there is no conflict.
+ This symbol's n_value gives the size of the string section associated
+ with this file. The symbol's n_strx (relative to the just-updated
+ string section start address) gives the name of the source file,
+ e.g. "foo.c", without any path information. The symbol's n_desc gives
+ the count of upcoming symbols associated with this file (not including
+ this one). */
+/* __define_stab (N_UNDF, 0x00, "UNDF") */
+
+/* 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.
+ "Static Sym". */
+__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. */
+__define_stab (N_MAIN, 0x2a, "MAIN")
+
+/* Solaris2: Read-only data symbols. */
+__define_stab (N_ROSYM, 0x2c, "ROSYM")
+
+/* Global symbol in Pascal.
+ Supposedly the value is its line number; I'm skeptical. */
+__define_stab (N_PC, 0x30, "PC")
+
+/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
+__define_stab (N_NSYMS, 0x32, "NSYMS")
+
+/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
+__define_stab (N_NOMAP, 0x34, "NOMAP")
+
+/* New stab from Solaris 2. Like N_SO, but for the object file. Two in
+ a row provide the build directory and the relative path of the .o from it.
+ Solaris2 uses this to avoid putting the stabs info into the linked
+ executable; this stab goes into the ".stab.index" section, and the debugger
+ reads the real stabs directly from the .o files instead. */
+__define_stab (N_OBJ, 0x38, "OBJ")
+
+/* New stab from Solaris 2. Options for the debugger, related to the
+ source language for this module. E.g. whether to use ANSI
+ integral promotions or traditional integral promotions. */
+__define_stab (N_OPT, 0x3c, "OPT")
+
+/* Register variable. Value is number of register. */
+__define_stab (N_RSYM, 0x40, "RSYM")
+
+/* Modula-2 compilation unit. Can someone say what info it contains? */
+__define_stab (N_M2C, 0x42, "M2C")
+
+/* Line number in text segment. Desc is the line number;
+ value is corresponding address. On Solaris2, the line number is
+ relative to the start of the current function. */
+__define_stab (N_SLINE, 0x44, "SLINE")
+
+/* Similar, for data segment. */
+__define_stab (N_DSLINE, 0x46, "DSLINE")
+
+/* Similar, for bss segment. */
+__define_stab (N_BSLINE, 0x48, "BSLINE")
+
+/* Sun's source-code browser stabs. ?? Don't know what the fields are.
+ Supposedly the field is "path to associated .cb file". THIS VALUE
+ OVERLAPS WITH N_BSLINE! */
+__define_stab (N_BROWS, 0x48, "BROWS")
+
+/* GNU Modula-2 definition module dependency. Value is the modification time
+ of the definition file. Other is non-zero if it is imported with the
+ GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
+ are enough empty fields? */
+__define_stab(N_DEFD, 0x4a, "DEFD")
+
+/* New in Solaris2. Function start/body/end line numbers. */
+__define_stab(N_FLINE, 0x4C, "FLINE")
+
+/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
+ and one is for C++. Still,... */
+/* GNU C++ exception variable. Name is variable name. */
+__define_stab (N_EHDECL, 0x50, "EHDECL")
+/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
+__define_stab (N_MOD2, 0x50, "MOD2")
+
+/* 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")
+
+/* Structure or union element. Value is offset in the structure. */
+__define_stab (N_SSYM, 0x60, "SSYM")
+
+/* Solaris2: Last stab emitted for module. */
+__define_stab (N_ENDM, 0x62, "ENDM")
+
+/* Name of main source file.
+ Value is starting text address of the compilation.
+ If multiple N_SO's appear, the first to contain a trailing / is the
+ compilation directory. The first to not contain a trailing / is the
+ source file name, relative to the compilation directory. Others (perhaps
+ resulting from cfront) are ignored.
+ On Solaris2, value is undefined, but desc is a source-language code. */
+
+__define_stab (N_SO, 0x64, "SO")
+
+/* Automatic variable in the stack. Value is offset from frame pointer.
+ Also used for type descriptions. */
+__define_stab (N_LSYM, 0x80, "LSYM")
+
+/* 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")
+
+/* Name of sub-source file (#include file).
+ Value is starting text address of the compilation. */
+__define_stab (N_SOL, 0x84, "SOL")
+
+/* 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")
+
+/* End of an include file. No name.
+ This and N_BINCL 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")
+
+/* Alternate entry point. Value is its address. */
+__define_stab (N_ENTRY, 0xa4, "ENTRY")
+
+/* 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.
+ On Solaris2, the value is relative to the start of the current function. */
+__define_stab (N_LBRAC, 0xc0, "LBRAC")
+
+/* Place holder for deleted include file. Replaces a N_BINCL and everything
+ up to the corresponding N_EINCL. The Sun linker generates these when
+ it finds multiple identical copies of the symbols from an include file.
+ This appears only in output from the Sun linker. */
+__define_stab (N_EXCL, 0xc2, "EXCL")
+
+/* Modula-2 scope information. Can someone say what info it contains? */
+__define_stab (N_SCOPE, 0xc4, "SCOPE")
+
+/* 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.
+ On Solaris2, the value is relative to the start of the current function. */
+__define_stab (N_RBRAC, 0xe0, "RBRAC")
+
+/* Begin named common block. Only the name is significant. */
+__define_stab (N_BCOMM, 0xe2, "BCOMM")
+
+/* End named common block. Only the name is significant
+ (and it should match the N_BCOMM). */
+__define_stab (N_ECOMM, 0xe4, "ECOMM")
+
+/* Member of a common block; value is offset within the common block.
+ This should occur within a BCOMM/ECOMM pair. */
+__define_stab (N_ECOML, 0xe8, "ECOML")
+
+/* Solaris2: Pascal "with" statement: type,,0,0,offset */
+__define_stab (N_WITH, 0xea, "WITH")
+
+/* 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")
+
+/* Second symbol entry containing a length-value for the preceding entry.
+ The value is the length. */
+__define_stab (N_LENG, 0xfe, "LENG")
+
+/* The above information, in matrix format.
+
+ STAB MATRIX
+ _________________________________________________
+ | 00 - 1F are not dbx stab symbols |
+ | In most cases, the low bit is the EXTernal bit|
+
+ | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
+ | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
+
+ | 08 BSS | 0A INDR | 0C FN_SEQ | 0E |
+ | 09 |EXT | 0B | 0D | 0F |
+
+ | 10 | 12 COMM | 14 SETA | 16 SETT |
+ | 11 | 13 | 15 | 17 |
+
+ | 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
+ | 19 | 1B | 1D | 1F FN |
+
+ |_______________________________________________|
+ | Debug entries with bit 01 set are unused. |
+ | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
+ | 28 LCSYM | 2A MAIN | 2C ROSYM | 2E |
+ | 30 PC | 32 NSYMS | 34 NOMAP | 36 |
+ | 38 OBJ | 3A | 3C OPT | 3E |
+ | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
+ | 48 BSLINE*| 4A DEFD | 4C FLINE | 4E |
+ | 50 EHDECL*| 52 | 54 CATCH | 56 |
+ | 58 | 5A | 5C | 5E |
+ | 60 SSYM | 62 ENDM | 64 SO | 66 |
+ | 68 | 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 WITH | EC | EE |
+ | F0 | F2 | F4 | F6 |
+ | F8 | FA | FC | FE LENG |
+ +-----------------------------------------------+
+ * 50 EHDECL is also MOD2.
+ * 48 BSLINE is also BROWS.
+ */
diff --git a/gnu/usr.bin/gdb/gdb/aout/stab_gnu.h b/gnu/usr.bin/gdb/gdb/aout/stab_gnu.h
new file mode 100644
index 000000000000..477b87d6d86d
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/aout/stab_gnu.h
@@ -0,0 +1,36 @@
+#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 "aout/stab.def"
+LAST_UNUSED_STAB_CODE
+};
+
+#undef __define_stab
+
+/* Definitions of "desc" field for N_SO stabs in Solaris2. */
+
+#define N_SO_AS 1
+#define N_SO_C 2
+#define N_SO_ANSI_C 3
+#define N_SO_CC 4 /* C++ */
+#define N_SO_FORTRAN 5
+#define N_SO_PASCAL 6
+
+/* Solaris2: Floating point type values in basic types. */
+
+#define NF_NONE 0
+#define NF_SINGLE 1 /* IEEE 32-bit */
+#define NF_DOUBLE 2 /* IEEE 64-bit */
+#define NF_COMPLEX 3 /* Fortran complex */
+#define NF_COMPLEX16 4 /* Fortran double complex */
+#define NF_COMPLEX32 5 /* Fortran complex*16 */
+#define NF_LDOUBLE 6 /* Long double (whatever that is) */
+
+#endif /* __GNU_STAB_ */
diff --git a/gnu/usr.bin/gdb/gdb/blockframe.c b/gnu/usr.bin/gdb/gdb/blockframe.c
new file mode 100644
index 000000000000..c7b3fdce26bd
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/blockframe.c
@@ -0,0 +1,821 @@
+/* Get info from stack frames;
+ convert between frames, blocks, functions and pc values.
+ Copyright 1986, 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "value.h" /* for read_register */
+#include "target.h" /* for target_has_stack */
+#include "inferior.h" /* for read_pc */
+
+/* Is ADDR inside 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.
+
+ A PC of zero is always considered to be the bottom of the stack. */
+
+int
+inside_entry_file (addr)
+ CORE_ADDR addr;
+{
+ if (addr == 0)
+ return 1;
+ if (symfile_objfile == 0)
+ return 0;
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+ /* Do not stop backtracing if the pc is in the call dummy
+ at the entry point. */
+ if (PC_IN_CALL_DUMMY (addr, 0, 0))
+ return 0;
+#endif
+ return (addr >= symfile_objfile -> ei.entry_file_lowpc &&
+ addr < symfile_objfile -> ei.entry_file_highpc);
+}
+
+/* Test a specified PC value to see if it is in the range of addresses
+ that correspond to the main() function. See comments above for why
+ we might want to do this.
+
+ Typically called from FRAME_CHAIN_VALID.
+
+ A PC of zero is always considered to be the bottom of the stack. */
+
+int
+inside_main_func (pc)
+CORE_ADDR pc;
+{
+ if (pc == 0)
+ return 1;
+ if (symfile_objfile == 0)
+ return 0;
+ return (symfile_objfile -> ei.main_func_lowpc <= pc &&
+ symfile_objfile -> ei.main_func_highpc > pc);
+}
+
+/* Test a specified PC value to see if it is in the range of addresses
+ that correspond to the process entry point function. See comments
+ in objfiles.h for why we might want to do this.
+
+ Typically called from FRAME_CHAIN_VALID.
+
+ A PC of zero is always considered to be the bottom of the stack. */
+
+int
+inside_entry_func (pc)
+CORE_ADDR pc;
+{
+ if (pc == 0)
+ return 1;
+ if (symfile_objfile == 0)
+ return 0;
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+ /* Do not stop backtracing if the pc is in the call dummy
+ at the entry point. */
+ if (PC_IN_CALL_DUMMY (pc, 0, 0))
+ return 0;
+#endif
+ return (symfile_objfile -> ei.entry_func_lowpc <= pc &&
+ symfile_objfile -> ei.entry_func_highpc > pc);
+}
+
+/* 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 */
+ char *name;
+
+ 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->pc = pc;
+ find_pc_partial_function (pc, &name, (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+ fci->signal_handler_caller = IN_SIGTRAMP (fci->pc, name);
+
+#ifdef INIT_EXTRA_FRAME_INFO
+ INIT_EXTRA_FRAME_INFO (0, 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 */
+}
+
+/* Flush the frame cache, and start a new one if necessary. */
+void
+reinit_frame_cache ()
+{
+ flush_cached_frames ();
+ if (target_has_stack)
+ {
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+ }
+ else
+ {
+ set_current_frame (0);
+ select_frame ((FRAME) 0, -1);
+ }
+}
+
+/* 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 lacks 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;
+#ifdef SKIP_PROLOGUE_FRAMELESS_P
+ /* This is faster, since only care whether there *is* a prologue,
+ not how long it is. */
+ SKIP_PROLOGUE_FRAMELESS_P (after_prologue);
+#else
+ SKIP_PROLOGUE (after_prologue);
+#endif
+ 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;
+}
+
+/* Default a few macros that people seldom redefine. */
+
+#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
+
+#ifndef FRAME_CHAIN_COMBINE
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+#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 = 0;
+ struct frame_info *prev;
+ int fromleaf = 0;
+ char *name;
+
+ /* 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 0
+ /* This screws value_of_variable, which just wants a nice clean
+ NULL return from block_innermost_frame if there are no frames.
+ I don't think I've ever seen this message happen otherwise.
+ And returning NULL here is a perfectly legitimate thing to do. */
+ if (!current_frame)
+ {
+ error ("You haven't set up a process's stack to examine.");
+ }
+#endif
+
+ 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);
+ }
+ if (address == 0)
+ return 0;
+
+ 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->signal_handler_caller = 0;
+
+/* This change should not be needed, FIXME! We should
+ determine whether any targets *need* INIT_FRAME_PC to happen
+ after INIT_EXTRA_FRAME_INFO and come up with a simple way to
+ express what goes on here.
+
+ INIT_EXTRA_FRAME_INFO is called from two places: create_new_frame
+ (where the PC is already set up) and here (where it isn't).
+ INIT_FRAME_PC is only called from here, always after
+ INIT_EXTRA_FRAME_INFO.
+
+ The catch is the MIPS, where INIT_EXTRA_FRAME_INFO requires the PC
+ value (which hasn't been set yet). Some other machines appear to
+ require INIT_EXTRA_FRAME_INFO before they can do INIT_FRAME_PC. Phoo.
+
+ We shouldn't need INIT_FRAME_PC_FIRST to add more complication to
+ an already overcomplicated part of GDB. gnu@cygnus.com, 15Sep92.
+
+ To answer the question, yes the sparc needs INIT_FRAME_PC after
+ INIT_EXTRA_FRAME_INFO. Suggested scheme:
+
+ SETUP_INNERMOST_FRAME()
+ Default version is just create_new_frame (read_fp ()),
+ read_pc ()). Machines with extra frame info would do that (or the
+ local equivalent) and then set the extra fields.
+ SETUP_ARBITRARY_FRAME(argc, argv)
+ Only change here is that create_new_frame would no longer init extra
+ frame info; SETUP_ARBITRARY_FRAME would have to do that.
+ INIT_PREV_FRAME(fromleaf, prev)
+ Replace INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC.
+ std_frame_pc(fromleaf, prev)
+ This is the default setting for INIT_PREV_FRAME. It just does what
+ the default INIT_FRAME_PC does. Some machines will call it from
+ INIT_PREV_FRAME (either at the beginning, the end, or in the middle).
+ Some machines won't use it.
+ kingdon@cygnus.com, 13Apr93. */
+
+#ifdef INIT_FRAME_PC_FIRST
+ INIT_FRAME_PC_FIRST (fromleaf, prev);
+#endif
+
+#ifdef INIT_EXTRA_FRAME_INFO
+ INIT_EXTRA_FRAME_INFO(fromleaf, 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 tm-sparc.h). We want the pc saved in the inferior frame. */
+ INIT_FRAME_PC(fromleaf, prev);
+
+ find_pc_partial_function (prev->pc, &name,
+ (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+ if (IN_SIGTRAMP (prev->pc, name))
+ prev->signal_handler_caller = 1;
+
+ 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 != 0 && fi->next->signal_handler_caller == 0)
+ /* We are not in the innermost frame and we were not interrupted
+ by a signal. 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;
+ register struct symbol *symbol;
+ register struct minimal_symbol *msymbol;
+ CORE_ADDR fstart;
+
+ if ((bl = block_for_pc (pc)) != NULL &&
+ (symbol = block_function (bl)) != NULL)
+ {
+ bl = SYMBOL_BLOCK_VALUE (symbol);
+ fstart = BLOCK_START (bl);
+ }
+ else if ((msymbol = lookup_minimal_symbol_by_pc (pc)) != NULL)
+ {
+ fstart = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ else
+ {
+ fstart = 0;
+ }
+ return (fstart);
+}
+
+/* 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);
+}
+
+/* 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-null. If ENDADDR is
+ non-null, then set *ENDADDR to be the end of the function
+ (exclusive), but passing ENDADDR as non-null means that the
+ function might cause symbols to be read. This function either
+ succeeds or fails (not halfway succeeds). If it succeeds, it sets
+ *NAME, *ADDRESS, and *ENDADDR to real information and returns 1.
+ If it fails, it sets *NAME, *ADDRESS, and *ENDADDR to zero
+ and returns 0. */
+
+int
+find_pc_partial_function (pc, name, address, endaddr)
+ CORE_ADDR pc;
+ char **name;
+ CORE_ADDR *address;
+ CORE_ADDR *endaddr;
+{
+ struct partial_symtab *pst;
+ struct symbol *f;
+ struct minimal_symbol *msymbol;
+ struct partial_symbol *psb;
+ struct obj_section *sec;
+
+ if (pc >= cache_pc_function_low && pc < cache_pc_function_high)
+ goto return_cached_value;
+
+ /* If sigtramp is in the u area, it counts as a function (especially
+ important for step_1). */
+#if defined SIGTRAMP_START
+ if (IN_SIGTRAMP (pc, (char *)NULL))
+ {
+ cache_pc_function_low = SIGTRAMP_START;
+ cache_pc_function_high = SIGTRAMP_END;
+ cache_pc_function_name = "<sigtramp>";
+
+ goto return_cached_value;
+ }
+#endif
+
+ msymbol = lookup_minimal_symbol_by_pc (pc);
+ pst = find_pc_psymtab (pc);
+ if (pst)
+ {
+ /* Need to read the symbols to get a good value for the end address. */
+ if (endaddr != NULL && !pst->readin)
+ {
+ /* Need to get the terminal in case symbol-reading produces
+ output. */
+ target_terminal_ours_for_output ();
+ PSYMTAB_TO_SYMTAB (pst);
+ }
+
+ if (pst->readin)
+ {
+ /* Checking whether the msymbol has a larger value is for the
+ "pathological" case mentioned in print_frame_info. */
+ f = find_pc_function (pc);
+ if (f != NULL
+ && (msymbol == NULL
+ || (BLOCK_START (SYMBOL_BLOCK_VALUE (f))
+ >= SYMBOL_VALUE_ADDRESS (msymbol))))
+ {
+ 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);
+ goto return_cached_value;
+ }
+ }
+ else
+ {
+ /* Now that static symbols go in the minimal symbol table, perhaps
+ we could just ignore the partial symbols. But at least for now
+ we use the partial or minimal symbol, whichever is larger. */
+ psb = find_pc_psymbol (pst, pc);
+
+ if (psb
+ && (msymbol == NULL ||
+ (SYMBOL_VALUE_ADDRESS (psb)
+ >= SYMBOL_VALUE_ADDRESS (msymbol))))
+ {
+ /* This case isn't being cached currently. */
+ if (address)
+ *address = SYMBOL_VALUE_ADDRESS (psb);
+ if (name)
+ *name = SYMBOL_NAME (psb);
+ /* endaddr non-NULL can't happen here. */
+ return 1;
+ }
+ }
+ }
+
+ /* Not in the normal symbol tables, see if the pc is in a known section.
+ If it's not, then give up. This ensures that anything beyond the end
+ of the text seg doesn't appear to be part of the last function in the
+ text segment. */
+
+ sec = find_pc_section (pc);
+
+ if (!sec)
+ msymbol = NULL;
+
+ /* Must be in the minimal symbol table. */
+ if (msymbol == NULL)
+ {
+ /* No available symbol. */
+ if (name != NULL)
+ *name = 0;
+ if (address != NULL)
+ *address = 0;
+ if (endaddr != NULL)
+ *endaddr = 0;
+ return 0;
+ }
+
+ /* See if we're in a transfer table for Sun shared libs. */
+
+ if (msymbol -> type == mst_text)
+ cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
+ else
+ /* It is a transfer table for Sun shared libraries. */
+ cache_pc_function_low = pc - FUNCTION_START_OFFSET;
+
+ cache_pc_function_name = SYMBOL_NAME (msymbol);
+
+ /* Use the lesser of the next minimal symbol, or the end of the section, as
+ the end of the function. */
+
+ if (SYMBOL_NAME (msymbol + 1) != NULL
+ && SYMBOL_VALUE_ADDRESS (msymbol + 1) < sec->endaddr)
+ cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + 1);
+ else
+ /* We got the start address from the last msymbol in the objfile.
+ So the end address is the end of the section. */
+ cache_pc_function_high = sec->endaddr;
+
+ return_cached_value:
+ if (address)
+ *address = cache_pc_function_low;
+ if (name)
+ *name = cache_pc_function_name;
+ if (endaddr)
+ *endaddr = cache_pc_function_high;
+ return 1;
+}
+
+/* Return the innermost stack frame executing inside of BLOCK,
+ or NULL if there is no such frame. If BLOCK is NULL, just return NULL. */
+
+FRAME
+block_innermost_frame (block)
+ struct block *block;
+{
+ struct frame_info *fi;
+ register FRAME frame;
+ register CORE_ADDR start;
+ register CORE_ADDR end;
+
+ if (block == NULL)
+ return NULL;
+
+ start = BLOCK_START (block);
+ 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;
+ }
+}
+
+#ifdef SIGCONTEXT_PC_OFFSET
+/* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp. */
+
+CORE_ADDR
+sigtramp_saved_pc (frame)
+ FRAME frame;
+{
+ CORE_ADDR sigcontext_addr;
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ int ptrbytes = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+ int sigcontext_offs = (2 * TARGET_INT_BIT) / TARGET_CHAR_BIT;
+
+ /* Get sigcontext address, it is the third parameter on the stack. */
+ if (frame->next)
+ sigcontext_addr = read_memory_integer (FRAME_ARGS_ADDRESS (frame->next)
+ + FRAME_ARGS_SKIP + sigcontext_offs,
+ ptrbytes);
+ else
+ sigcontext_addr = read_memory_integer (read_register (SP_REGNUM)
+ + sigcontext_offs,
+ ptrbytes);
+
+ /* Don't cause a memory_error when accessing sigcontext in case the stack
+ layout has changed or the stack is corrupt. */
+ target_read_memory (sigcontext_addr + SIGCONTEXT_PC_OFFSET, buf, ptrbytes);
+ return extract_unsigned_integer (buf, ptrbytes);
+}
+#endif /* SIGCONTEXT_PC_OFFSET */
+
+void
+_initialize_blockframe ()
+{
+ obstack_init (&frame_cache_obstack);
+}
diff --git a/gnu/usr.bin/gdb/gdb/breakpoint.c b/gnu/usr.bin/gdb/gdb/breakpoint.c
new file mode 100644
index 000000000000..69694c016f67
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/breakpoint.c
@@ -0,0 +1,3301 @@
+/* Everything about breakpoints, for GDB.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "gdbtypes.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 "language.h"
+#include <string.h>
+#include "demangle.h"
+
+/* local function prototypes */
+
+static void
+catch_command_1 PARAMS ((char *, int, int));
+
+static void
+enable_delete_command PARAMS ((char *, int));
+
+static void
+enable_delete_breakpoint PARAMS ((struct breakpoint *));
+
+static void
+enable_once_command PARAMS ((char *, int));
+
+static void
+enable_once_breakpoint PARAMS ((struct breakpoint *));
+
+static void
+disable_command PARAMS ((char *, int));
+
+static void
+disable_breakpoint PARAMS ((struct breakpoint *));
+
+static void
+enable_command PARAMS ((char *, int));
+
+static void
+enable_breakpoint PARAMS ((struct breakpoint *));
+
+static void
+map_breakpoint_numbers PARAMS ((char *, void (*)(struct breakpoint *)));
+
+static void
+ignore_command PARAMS ((char *, int));
+
+static int
+breakpoint_re_set_one PARAMS ((char *));
+
+static void
+delete_command PARAMS ((char *, int));
+
+static void
+clear_command PARAMS ((char *, int));
+
+static void
+catch_command PARAMS ((char *, int));
+
+static struct symtabs_and_lines
+get_catch_sals PARAMS ((int));
+
+static void
+watch_command PARAMS ((char *, int));
+
+static void
+tbreak_command PARAMS ((char *, int));
+
+static void
+break_command_1 PARAMS ((char *, int, int));
+
+static void
+mention PARAMS ((struct breakpoint *));
+
+static struct breakpoint *
+set_raw_breakpoint PARAMS ((struct symtab_and_line));
+
+static void
+check_duplicates PARAMS ((CORE_ADDR));
+
+static void
+describe_other_breakpoints PARAMS ((CORE_ADDR));
+
+static void
+breakpoints_info PARAMS ((char *, int));
+
+static void
+breakpoint_1 PARAMS ((int, int));
+
+static bpstat
+bpstat_alloc PARAMS ((struct breakpoint *, bpstat));
+
+static int
+breakpoint_cond_eval PARAMS ((char *));
+
+static void
+cleanup_executing_breakpoints PARAMS ((int));
+
+static void
+commands_command PARAMS ((char *, int));
+
+static void
+condition_command PARAMS ((char *, int));
+
+static int
+get_number PARAMS ((char **));
+
+static void
+set_breakpoint_count PARAMS ((int));
+
+
+extern int addressprint; /* Print machine addresses? */
+extern int demangle; /* Print de-mangled symbol names? */
+
+/* Are we executing breakpoint commands? */
+static int executing_breakpoint_commands;
+
+/* Walk the following statement or block through all breakpoints.
+ ALL_BREAKPOINTS_SAFE does so even if the statment deletes the current
+ breakpoint. */
+
+#define ALL_BREAKPOINTS(b) for (b = breakpoint_chain; b; b = b->next)
+
+#define ALL_BREAKPOINTS_SAFE(b,tmp) \
+ for (b = breakpoint_chain; \
+ b? (tmp=b->next, 1): 0; \
+ b = tmp)
+
+/* 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_longest (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;
+
+/* Flag indicating extra verbosity for xgdb. */
+extern int xgdb_verbose;
+
+/* *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
+ {
+ if (*p == '-')
+ ++p;
+ 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;
+}
+
+/* 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 ((PTR)b->cond);
+ b->cond = 0;
+ }
+ if (b->cond_string != NULL)
+ free ((PTR)b->cond_string);
+
+ if (*p == 0)
+ {
+ b->cond = 0;
+ b->cond_string = NULL;
+ if (from_tty)
+ printf_filtered ("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_exp_1 (&arg, block_for_pc (b->address), 0);
+ if (*arg)
+ error ("Junk at end of expression");
+ }
+ return;
+ }
+
+ error ("No breakpoint number %d.", bnum);
+}
+
+/* ARGSUSED */
+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 (from_tty && input_from_terminal_p ())
+ printf_filtered ("Type commands for when breakpoint %d is hit, one per line.\n\
+End with a line saying just \"end\".\n", bnum);
+ l = read_command_lines ();
+ free_command_lines (&b->commands);
+ b->commands = l;
+ return;
+ }
+ error ("No breakpoint number %d.", bnum);
+}
+
+extern int memory_breakpoint_size; /* from mem-break.c */
+
+/* Like target_read_memory() but if breakpoints are inserted, return
+ the shadow contents instead of the breakpoints themselves.
+
+ 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 (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ unsigned len;
+{
+ int status;
+ struct breakpoint *b;
+
+ if (memory_breakpoint_size < 0)
+ /* No breakpoints on this machine. FIXME: This should be
+ dependent on the debugging target. Probably want
+ target_insert_breakpoint to return a size, saying how many
+ bytes of the shadow contents are used, or perhaps have
+ something like target_xfer_shadow. */
+ return target_read_memory (memaddr, myaddr, len);
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->type == bp_watchpoint || !b->inserted)
+ continue;
+ else if (b->address + memory_breakpoint_size <= 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 = memory_breakpoint_size;
+ /* 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);
+ }
+
+ memcpy (myaddr + membpt - memaddr,
+ b->shadow_contents + bptoffset, 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);
+}
+
+/* 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->type != bp_watchpoint
+ && 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);
+#ifdef ONE_PROCESS_WRITETEXT
+ fprintf (stderr,
+ "The same program may be running in another process.\n");
+#endif
+ 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->type != bp_watchpoint && 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 %s",
+ local_hex_string((unsigned long) b->address));
+ printf (", shadow %s",
+ local_hex_string((unsigned long) b->shadow_contents[0]));
+ printf (", %s.\n",
+ local_hex_string((unsigned long) b->shadow_contents[1]));
+#endif /* BREAKPOINT_DEBUG */
+ }
+
+ return 0;
+}
+
+/* Clear the "inserted" flag in all breakpoints. */
+
+void
+mark_breakpoints_out ()
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ b->inserted = 0;
+}
+
+/* Clear the "inserted" flag in all breakpoints and delete any breakpoints
+ which should go away between runs of the program. */
+
+void
+breakpoint_init_inferior ()
+{
+ register struct breakpoint *b, *temp;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ b->inserted = 0;
+
+ /* If the call dummy breakpoint is at the entry point it will
+ cause problems when the inferior is rerun, so we better
+ get rid of it. */
+ if (b->type == bp_call_dummy)
+ delete_breakpoint (b);
+ }
+}
+
+/* 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;
+}
+
+/* breakpoint_match_thread (PC, PID) returns true if the breakpoint at PC
+ is valid for process/thread PID. */
+
+int
+breakpoint_thread_match (pc, pid)
+ CORE_ADDR pc;
+ int pid;
+{
+ struct breakpoint *b;
+ int thread;
+
+ thread = pid_to_thread_id (pid);
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled
+ && b->address == pc
+ && (b->thread == -1 || b->thread == thread))
+ return 1;
+
+ return 0;
+}
+
+
+/* bpstat stuff. External routines' interfaces are documented
+ in breakpoint.h. */
+
+/* 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 (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 ((PTR)p);
+ p = q;
+ }
+ *bsp = NULL;
+}
+
+/* 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 (bs)
+ bpstat bs;
+{
+ bpstat p = NULL;
+ bpstat tmp;
+ bpstat retval = NULL;
+
+ if (bs == NULL)
+ return bs;
+
+ for (; bs != NULL; bs = bs->next)
+ {
+ tmp = (bpstat) xmalloc (sizeof (*tmp));
+ memcpy (tmp, bs, 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;
+}
+
+/* Find the bpstat associated with this breakpoint */
+
+bpstat
+bpstat_find_breakpoint(bsp, breakpoint)
+ bpstat bsp;
+ struct breakpoint *breakpoint;
+{
+ if (bsp == NULL) return NULL;
+
+ for (;bsp != NULL; bsp = bsp->next) {
+ if (bsp->breakpoint_at == breakpoint) return bsp;
+ }
+ return NULL;
+}
+
+/* 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 (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 */
+ }
+}
+
+/* Modify BS so that the actions will not be performed. */
+
+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;
+ }
+ }
+}
+
+/* Stub for cleaning up our state if we error-out of a breakpoint command */
+/* ARGSUSED */
+static void
+cleanup_executing_breakpoints (ignore)
+ int ignore;
+{
+ executing_breakpoint_commands = 0;
+}
+
+/* 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;
+ struct cleanup *old_chain;
+
+ executing_breakpoint_commands = 1;
+ old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
+
+top:
+ bs = *bsp;
+
+ 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;
+ }
+ }
+
+ executing_breakpoint_commands = 0;
+ discard_cleanups (old_chain);
+}
+
+/* This is the normal print_it function for a bpstat. In the future,
+ much of this logic could (should?) be moved to bpstat_stop_status,
+ by having it set different print_it functions. */
+
+static int
+print_it_normal (bs)
+ bpstat bs;
+{
+ /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
+ which has since been deleted. */
+ if (bs->breakpoint_at == NULL
+ || (bs->breakpoint_at->type != bp_breakpoint
+ && bs->breakpoint_at->type != bp_watchpoint))
+ return 0;
+
+ if (bs->breakpoint_at->type == bp_breakpoint)
+ {
+ /* 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 0;
+ }
+ /* We can't deal with it. Maybe another member of the bpstat chain can. */
+ return -1;
+}
+
+/* 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). */
+/* Currently we always return zero. */
+int
+bpstat_print (bs)
+ bpstat bs;
+{
+ int val;
+
+ if (bs == NULL)
+ return 0;
+
+ val = (*bs->print_it) (bs);
+ if (val >= 0)
+ return val;
+
+ /* Maybe another breakpoint in the chain caused us to stop.
+ (Currently all watchpoints go on the bpstat whether hit or
+ not. That probably could (should) be changed, provided care is taken
+ with respect to bpstat_explains_signal). */
+ if (bs->next)
+ return bpstat_print (bs->next);
+
+ /* We reached the end of the chain without printing anything. */
+ 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 char * to
+ make it pass through catch_errors. */
+
+static int
+breakpoint_cond_eval (exp)
+ char *exp;
+{
+ return !value_true (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->old_val = NULL;
+ bs->print_it = print_it_normal;
+ return bs;
+}
+
+/* Return the frame which we can use to evaluate the expression
+ whose valid block is valid_block, or NULL if not in scope.
+
+ This whole concept is probably not the way to do things (it is incredibly
+ slow being the main reason, not to mention fragile (e.g. the sparc
+ frame pointer being fetched as 0 bug causes it to stop)). Instead,
+ introduce a version of "struct frame" which survives over calls to the
+ inferior, but which is better than FRAME_ADDR in the sense that it lets
+ us evaluate expressions relative to that frame (on some machines, it
+ can just be a FRAME_ADDR). Save one of those instead of (or in addition
+ to) the exp_valid_block, and then use it to evaluate the watchpoint
+ expression, with no need to do all this backtracing every time.
+
+ Or better yet, what if it just copied the struct frame and its next
+ frame? Off the top of my head, I would think that would work
+ because things like (a29k) rsize and msize, or (sparc) bottom just
+ depend on the frame, and aren't going to be different just because
+ the inferior has done something. Trying to recalculate them
+ strikes me as a lot of work, possibly even impossible. Saving the
+ next frame is needed at least on a29k, where get_saved_register
+ uses fi->next->saved_msp. For figuring out whether that frame is
+ still on the stack, I guess this needs to be machine-specific (e.g.
+ a29k) but I think
+
+ read_fp () INNER_THAN watchpoint_frame->frame
+
+ would generally work.
+
+ Of course the scope of the expression could be less than a whole
+ function; perhaps if the innermost frame is the one which the
+ watchpoint is relative to (another machine-specific thing, usually
+
+ FRAMELESS_FUNCTION_INVOCATION (get_current_frame(), fromleaf)
+ read_fp () == wp_frame->frame
+ && !fromleaf
+
+ ), *then* it could do a
+
+ contained_in (get_current_block (), wp->exp_valid_block).
+
+ */
+
+FRAME
+within_scope (valid_block)
+ struct block *valid_block;
+{
+ FRAME fr = get_current_frame ();
+ struct frame_info *fi = get_frame_info (fr);
+ CORE_ADDR func_start;
+
+ /* If caller_pc_valid is true, we are stepping through
+ a function prologue, which is bounded by callee_func_start
+ (inclusive) and callee_prologue_end (exclusive).
+ caller_pc is the pc of the caller.
+
+ Yes, this is hairy. */
+ static int caller_pc_valid = 0;
+ static CORE_ADDR caller_pc;
+ static CORE_ADDR callee_func_start;
+ static CORE_ADDR callee_prologue_end;
+
+ find_pc_partial_function (fi->pc, (PTR)NULL, &func_start, (CORE_ADDR *)NULL);
+ func_start += FUNCTION_START_OFFSET;
+ if (fi->pc == func_start)
+ {
+ /* We just called a function. The only other case I
+ can think of where the pc would equal the pc of the
+ start of a function is a frameless function (i.e.
+ no prologue) where we branch back to the start
+ of the function. In that case, SKIP_PROLOGUE won't
+ find one, and we'll clear caller_pc_valid a few lines
+ down. */
+ caller_pc_valid = 1;
+ caller_pc = SAVED_PC_AFTER_CALL (fr);
+ callee_func_start = func_start;
+ SKIP_PROLOGUE (func_start);
+ callee_prologue_end = func_start;
+ }
+ if (caller_pc_valid)
+ {
+ if (fi->pc < callee_func_start
+ || fi->pc >= callee_prologue_end)
+ caller_pc_valid = 0;
+ }
+
+ if (contained_in (block_for_pc (caller_pc_valid
+ ? caller_pc
+ : fi->pc),
+ valid_block))
+ {
+ return fr;
+ }
+ fr = get_prev_frame (fr);
+
+ /* If any active frame is in the exp_valid_block, then it's
+ OK. Note that this might not be the same invocation of
+ the exp_valid_block that we were watching a little while
+ ago, or the same one as when the watchpoint was set (e.g.
+ we are watching a local variable in a recursive function.
+ When we return from a recursive invocation, then we are
+ suddenly watching a different instance of the variable).
+
+ At least for now I am going to consider this a feature. */
+ for (; fr != NULL; fr = get_prev_frame (fr))
+ {
+ fi = get_frame_info (fr);
+ if (contained_in (block_for_pc (fi->pc),
+ valid_block))
+ {
+ return fr;
+ }
+ }
+ return NULL;
+}
+
+/* Possible return values for watchpoint_check (this can't be an enum
+ because of check_errors). */
+/* The watchpoint has been disabled. */
+#define WP_DISABLED 1
+/* The value has changed. */
+#define WP_VALUE_CHANGED 2
+/* The value has not changed. */
+#define WP_VALUE_NOT_CHANGED 3
+
+/* Check watchpoint condition. */
+static int
+watchpoint_check (p)
+ char *p;
+{
+ bpstat bs = (bpstat) p;
+ FRAME fr;
+
+ int within_current_scope;
+ if (bs->breakpoint_at->exp_valid_block == NULL)
+ within_current_scope = 1;
+ else
+ {
+ fr = within_scope (bs->breakpoint_at->exp_valid_block);
+ within_current_scope = fr != NULL;
+ if (within_current_scope)
+ /* If we end up stopping, the current frame will get selected
+ in normal_stop. So this call to select_frame won't affect
+ the user. */
+ select_frame (fr, -1);
+ }
+
+ if (within_current_scope)
+ {
+ /* We use value_{,free_to_}mark because it could be a
+ *long* time before we return to the command level and
+ call free_all_values. We can't call free_all_values because
+ we might be in the middle of evaluating a function call. */
+
+ value mark = value_mark ();
+ value new_val = evaluate_expression (bs->breakpoint_at->exp);
+ if (!value_equal (bs->breakpoint_at->val, new_val))
+ {
+ release_value (new_val);
+ value_free_to_mark (mark);
+ bs->old_val = bs->breakpoint_at->val;
+ bs->breakpoint_at->val = new_val;
+ /* We will stop here */
+ return WP_VALUE_CHANGED;
+ }
+ else
+ {
+ /* Nothing changed, don't do anything. */
+ value_free_to_mark (mark);
+ /* We won't stop here */
+ return WP_VALUE_NOT_CHANGED;
+ }
+ }
+ 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). */
+ bs->breakpoint_at->enable = disabled;
+ printf_filtered ("\
+Watchpoint %d disabled because the program has left the block in\n\
+which its expression is valid.\n", bs->breakpoint_at->number);
+ return WP_DISABLED;
+ }
+}
+
+/* This is used when everything which needs to be printed has
+ already been printed. But we still want to print the frame. */
+static int
+print_it_done (bs)
+ bpstat bs;
+{
+ return 0;
+}
+
+/* This is used when nothing should be printed for this bpstat entry. */
+
+static int
+print_it_noop (bs)
+ bpstat bs;
+{
+ return -1;
+}
+
+/* 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). NOT_A_BREAKPOINT is nonzero
+ if this is known to not be a real breakpoint (it could still be a
+ watchpoint, though). */
+
+/* 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.
+
+ Each element of the chain refers to a particular breakpoint or
+ watchpoint at which we have stopped. (We may have stopped for
+ several reasons concurrently.)
+
+ Each element of the chain has valid next, breakpoint_at,
+ commands, FIXME??? fields.
+
+ */
+
+bpstat
+bpstat_stop_status (pc, frame_address, not_a_breakpoint)
+ CORE_ADDR *pc;
+ FRAME_ADDR frame_address;
+ int not_a_breakpoint;
+{
+ register struct breakpoint *b;
+ CORE_ADDR bp_addr;
+#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
+ /* True if we've hit a breakpoint (as opposed to a watchpoint). */
+ int real_breakpoint = 0;
+#endif
+ /* Root of the chain of bpstat's */
+ struct bpstat 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)
+ {
+ if (b->enable == disabled)
+ continue;
+
+ if (b->type != bp_watchpoint && b->address != bp_addr)
+ continue;
+
+ if (b->type != bp_watchpoint && not_a_breakpoint)
+ continue;
+
+ /* Come here if it's a watchpoint, or if the break address matches */
+
+ bs = bpstat_alloc (b, bs); /* Alloc a bpstat to explain stop */
+
+ bs->stop = 1;
+ bs->print = 1;
+
+ if (b->type == bp_watchpoint)
+ {
+ static char message1[] =
+ "Error evaluating expression for watchpoint %d\n";
+ char message[sizeof (message1) + 30 /* slop */];
+ sprintf (message, message1, b->number);
+ switch (catch_errors (watchpoint_check, (char *) bs, message,
+ RETURN_MASK_ALL))
+ {
+ case WP_DISABLED:
+ /* We've already printed what needs to be printed. */
+ bs->print_it = print_it_done;
+ /* Stop. */
+ break;
+ case WP_VALUE_CHANGED:
+ /* Stop. */
+ break;
+ case WP_VALUE_NOT_CHANGED:
+ /* Don't stop. */
+ bs->print_it = print_it_noop;
+ bs->stop = 0;
+ continue;
+ default:
+ /* Can't happen. */
+ /* FALLTHROUGH */
+ case 0:
+ /* Error from catch_errors. */
+ b->enable = disabled;
+ printf_filtered ("Watchpoint %d disabled.\n", b->number);
+ /* We've already printed what needs to be printed. */
+ bs->print_it = print_it_done;
+ /* Stop. */
+ break;
+ }
+ }
+#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
+ else
+ real_breakpoint = 1;
+#endif
+
+ if (b->frame && b->frame != frame_address)
+ bs->stop = 0;
+ else
+ {
+ int value_is_zero = 0;
+
+ 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_is_zero
+ = catch_errors (breakpoint_cond_eval, (char *)(b->cond),
+ "Error in testing breakpoint condition:\n",
+ RETURN_MASK_ALL);
+ /* FIXME-someday, should give breakpoint # */
+ free_all_values ();
+ }
+ if (b->cond && value_is_zero)
+ {
+ bs->stop = 0;
+ }
+ else if (b->ignore_count > 0)
+ {
+ b->ignore_count--;
+ bs->stop = 0;
+ }
+ else
+ {
+ /* We will stop here */
+ if (b->disposition == disable)
+ b->enable = disabled;
+ bs->commands = b->commands;
+ if (b->silent)
+ bs->print = 0;
+ if (bs->commands && STREQ ("silent", bs->commands->line))
+ {
+ bs->commands = bs->commands->next;
+ bs->print = 0;
+ }
+ }
+ }
+ /* Print nothing for this entry if we dont stop or if we dont print. */
+ if (bs->stop == 0 || bs->print == 0)
+ bs->print_it = print_it_noop;
+ }
+
+ bs->next = NULL; /* Terminate the chain */
+ bs = root_bs->next; /* Re-grab the head of the chain */
+#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
+ if (bs)
+ {
+ if (real_breakpoint)
+ {
+ *pc = bp_addr;
+#if defined (SHIFT_INST_REGS)
+ SHIFT_INST_REGS();
+#else /* No SHIFT_INST_REGS. */
+ write_pc (bp_addr);
+#endif /* No SHIFT_INST_REGS. */
+ }
+ }
+#endif /* DECR_PC_AFTER_BREAK != 0. */
+ return bs;
+}
+
+/* Tell what to do about this bpstat. */
+struct bpstat_what
+bpstat_what (bs)
+ bpstat bs;
+{
+ /* Classify each bpstat as one of the following. */
+ enum class {
+ /* This bpstat element has no effect on the main_action. */
+ no_effect = 0,
+
+ /* There was a watchpoint, stop but don't print. */
+ wp_silent,
+
+ /* There was a watchpoint, stop and print. */
+ wp_noisy,
+
+ /* There was a breakpoint but we're not stopping. */
+ bp_nostop,
+
+ /* There was a breakpoint, stop but don't print. */
+ bp_silent,
+
+ /* There was a breakpoint, stop and print. */
+ bp_noisy,
+
+ /* We hit the longjmp breakpoint. */
+ long_jump,
+
+ /* We hit the longjmp_resume breakpoint. */
+ long_resume,
+
+ /* This is just used to count how many enums there are. */
+ class_last
+ };
+
+ /* Here is the table which drives this routine. So that we can
+ format it pretty, we define some abbreviations for the
+ enum bpstat_what codes. */
+#define keep_c BPSTAT_WHAT_KEEP_CHECKING
+#define stop_s BPSTAT_WHAT_STOP_SILENT
+#define stop_n BPSTAT_WHAT_STOP_NOISY
+#define single BPSTAT_WHAT_SINGLE
+#define setlr BPSTAT_WHAT_SET_LONGJMP_RESUME
+#define clrlr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
+#define clrlrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
+/* "Can't happen." Might want to print an error message.
+ abort() is not out of the question, but chances are GDB is just
+ a bit confused, not unusable. */
+#define err BPSTAT_WHAT_STOP_NOISY
+
+ /* Given an old action and a class, come up with a new action. */
+ /* One interesting property of this table is that wp_silent is the same
+ as bp_silent and wp_noisy is the same as bp_noisy. That is because
+ after stopping, the check for whether to step over a breakpoint
+ (BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without
+ reference to how we stopped. We retain separate wp_silent and bp_silent
+ codes in case we want to change that someday. */
+ static const enum bpstat_what_main_action
+ table[(int)class_last][(int)BPSTAT_WHAT_LAST] =
+ {
+ /* old action */
+ /* keep_c stop_s stop_n single setlr clrlr clrlrs */
+
+/*no_effect*/ {keep_c, stop_s, stop_n, single, setlr , clrlr , clrlrs},
+/*wp_silent*/ {stop_s, stop_s, stop_n, stop_s, stop_s, stop_s, stop_s},
+/*wp_noisy*/ {stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, stop_n},
+/*bp_nostop*/ {single, stop_s, stop_n, single, setlr , clrlrs, clrlrs},
+/*bp_silent*/ {stop_s, stop_s, stop_n, stop_s, stop_s, stop_s, stop_s},
+/*bp_noisy*/ {stop_n, stop_n, stop_n, stop_n, stop_n, stop_n, stop_n},
+/*long_jump*/ {setlr , stop_s, stop_n, setlr , err , err , err },
+/*long_resume*/ {clrlr , stop_s, stop_n, clrlrs, err , err , err }
+ };
+#undef keep_c
+#undef stop_s
+#undef stop_n
+#undef single
+#undef setlr
+#undef clrlr
+#undef clrlrs
+#undef err
+ enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
+ struct bpstat_what retval;
+
+ retval.call_dummy = 0;
+ retval.step_resume = 0;
+ for (; bs != NULL; bs = bs->next)
+ {
+ enum class bs_class = no_effect;
+ if (bs->breakpoint_at == NULL)
+ /* I suspect this can happen if it was a momentary breakpoint
+ which has since been deleted. */
+ continue;
+ switch (bs->breakpoint_at->type)
+ {
+ case bp_breakpoint:
+ case bp_until:
+ case bp_finish:
+ if (bs->stop)
+ {
+ if (bs->print)
+ bs_class = bp_noisy;
+ else
+ bs_class = bp_silent;
+ }
+ else
+ bs_class = bp_nostop;
+ break;
+ case bp_watchpoint:
+ if (bs->stop)
+ {
+ if (bs->print)
+ bs_class = wp_noisy;
+ else
+ bs_class = wp_silent;
+ }
+ else
+ /* There was a watchpoint, but we're not stopping. This requires
+ no further action. */
+ bs_class = no_effect;
+ break;
+ case bp_longjmp:
+ bs_class = long_jump;
+ break;
+ case bp_longjmp_resume:
+ bs_class = long_resume;
+ break;
+ case bp_step_resume:
+#if 0
+ /* Need to temporarily disable this until we can fix the bug
+ with nexting over a breakpoint with ->stop clear causing
+ an infinite loop. For now, treat the breakpoint as having
+ been hit even if the frame is wrong. */
+ if (bs->stop)
+ {
+#endif
+ retval.step_resume = 1;
+ /* We don't handle this via the main_action. */
+ bs_class = no_effect;
+#if 0
+ }
+ else
+ /* It is for the wrong frame. */
+ bs_class = bp_nostop;
+#endif
+ break;
+ case bp_call_dummy:
+ /* Make sure the action is stop (silent or noisy), so infrun.c
+ pops the dummy frame. */
+ bs_class = bp_silent;
+ retval.call_dummy = 1;
+ break;
+ }
+ current_action = table[(int)bs_class][(int)current_action];
+ }
+ retval.main_action = current_action;
+ return retval;
+}
+
+/* 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 ()
+{
+ struct breakpoint *b;
+ ALL_BREAKPOINTS (b)
+ if (b->enable == enabled && b->type == bp_watchpoint)
+ return 1;
+ return 0;
+}
+
+/* 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, allflag)
+ int bnum;
+ int allflag;
+{
+ register struct breakpoint *b;
+ register struct command_line *l;
+ register struct symbol *sym;
+ CORE_ADDR last_addr = (CORE_ADDR)-1;
+ int found_a_breakpoint = 0;
+ static char *bptypes[] = {"breakpoint", "until", "finish", "watchpoint",
+ "longjmp", "longjmp resume", "step resume",
+ "call dummy" };
+ static char *bpdisps[] = {"del", "dis", "keep"};
+ static char bpenables[] = "ny";
+ char wrap_indent[80];
+
+ ALL_BREAKPOINTS (b)
+ if (bnum == -1
+ || bnum == b->number)
+ {
+/* We only print out user settable breakpoints unless the allflag is set. */
+ if (!allflag
+ && b->type != bp_breakpoint
+ && b->type != bp_watchpoint)
+ continue;
+
+ if (!found_a_breakpoint++)
+ printf_filtered ("Num Type Disp Enb %sWhat\n",
+ addressprint ? "Address " : "");
+
+ printf_filtered ("%-3d %-14s %-4s %-3c ",
+ b->number,
+ bptypes[(int)b->type],
+ bpdisps[(int)b->disposition],
+ bpenables[(int)b->enable]);
+ strcpy (wrap_indent, " ");
+ if (addressprint)
+ strcat (wrap_indent, " ");
+ switch (b->type)
+ {
+ case bp_watchpoint:
+ print_expression (b->exp, stdout);
+ break;
+
+ case bp_breakpoint:
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ case bp_step_resume:
+ case bp_call_dummy:
+ if (addressprint)
+ printf_filtered ("%s ", local_hex_string_custom ((unsigned long) b->address, "08l"));
+
+ last_addr = b->address;
+ if (b->source_file)
+ {
+ sym = find_pc_function (b->address);
+ if (sym)
+ {
+ fputs_filtered ("in ", stdout);
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), stdout);
+ wrap_here (wrap_indent);
+ fputs_filtered (" at ", stdout);
+ }
+ fputs_filtered (b->source_file, stdout);
+ printf_filtered (":%d", b->line_number);
+ }
+ else
+ print_address_symbolic (b->address, stdout, demangle, " ");
+ break;
+ }
+
+ printf_filtered ("\n");
+
+ if (b->frame)
+ printf_filtered ("\tstop only in stack frame at %s\n",
+ local_hex_string((unsigned long) 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 (!found_a_breakpoint)
+ {
+ if (bnum == -1)
+ printf_filtered ("No breakpoints or watchpoints.\n");
+ else
+ printf_filtered ("No breakpoint or watchpoint number %d.\n", bnum);
+ }
+ else
+ /* 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);
+}
+
+/* ARGSUSED */
+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);
+}
+
+#if MAINTENANCE_CMDS
+
+/* ARGSUSED */
+static void
+maintenance_info_breakpoints (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);
+}
+
+#endif
+
+/* 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 %s.\n", local_hex_string((unsigned long) pc));
+ }
+}
+
+/* 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;
+
+ if (address == 0) /* Watchpoints are uninteresting */
+ return;
+
+ 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.
+
+ ==> This routine should not be called if there is a chance of later
+ error(); otherwise it leaves a bogus breakpoint on the chain. Validate
+ your arguments BEFORE calling this routine! */
+
+static struct breakpoint *
+set_raw_breakpoint (sal)
+ struct symtab_and_line sal;
+{
+ register struct breakpoint *b, *b1;
+
+ b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
+ memset (b, 0, sizeof (*b));
+ b->address = sal.pc;
+ if (sal.symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file = savestring (sal.symtab->filename,
+ strlen (sal.symtab->filename));
+ b->thread = -1;
+ b->line_number = sal.line;
+ b->enable = enabled;
+ b->next = 0;
+ b->silent = 0;
+ b->ignore_count = 0;
+ b->commands = NULL;
+ b->frame = 0;
+
+ /* 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;
+}
+
+static void
+create_longjmp_breakpoint(func_name)
+ char *func_name;
+{
+ struct symtab_and_line sal;
+ struct breakpoint *b;
+ static int internal_breakpoint_number = -1;
+
+ if (func_name != NULL)
+ {
+ struct minimal_symbol *m;
+
+ m = lookup_minimal_symbol(func_name, (struct objfile *)NULL);
+ if (m)
+ sal.pc = SYMBOL_VALUE_ADDRESS (m);
+ else
+ return;
+ }
+ else
+ sal.pc = 0;
+
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ b = set_raw_breakpoint(sal);
+ if (!b) return;
+
+ b->type = func_name != NULL ? bp_longjmp : bp_longjmp_resume;
+ b->disposition = donttouch;
+ b->enable = disabled;
+ b->silent = 1;
+ if (func_name)
+ b->addr_string = strsave(func_name);
+ b->number = internal_breakpoint_number--;
+}
+
+/* Call this routine when stepping and nexting to enable a breakpoint if we do
+ a longjmp(). When we hit that breakpoint, call
+ set_longjmp_resume_breakpoint() to figure out where we are going. */
+
+void
+enable_longjmp_breakpoint()
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->type == bp_longjmp)
+ {
+ b->enable = enabled;
+ check_duplicates (b->address);
+ }
+}
+
+void
+disable_longjmp_breakpoint()
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if ( b->type == bp_longjmp
+ || b->type == bp_longjmp_resume)
+ {
+ b->enable = disabled;
+ check_duplicates (b->address);
+ }
+}
+
+/* Call this after hitting the longjmp() breakpoint. Use this to set a new
+ breakpoint at the target of the jmp_buf.
+
+ FIXME - This ought to be done by setting a temporary breakpoint that gets
+ deleted automatically...
+*/
+
+void
+set_longjmp_resume_breakpoint(pc, frame)
+ CORE_ADDR pc;
+ FRAME frame;
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->type == bp_longjmp_resume)
+ {
+ b->address = pc;
+ b->enable = enabled;
+ if (frame != NULL)
+ b->frame = FRAME_FP(frame);
+ else
+ b->frame = 0;
+ check_duplicates (b->address);
+ return;
+ }
+}
+
+/* Set a breakpoint that will evaporate an end of command
+ at address specified by SAL.
+ Restrict it to frame FRAME if FRAME is nonzero. */
+
+struct breakpoint *
+set_momentary_breakpoint (sal, frame, type)
+ struct symtab_and_line sal;
+ FRAME frame;
+ enum bptype type;
+{
+ register struct breakpoint *b;
+ b = set_raw_breakpoint (sal);
+ b->type = type;
+ b->enable = enabled;
+ b->disposition = donttouch;
+ b->frame = (frame ? FRAME_FP (frame) : 0);
+ return b;
+}
+
+#if 0
+void
+clear_momentary_breakpoints ()
+{
+ register struct breakpoint *b;
+ ALL_BREAKPOINTS (b)
+ if (b->disposition == delete)
+ {
+ delete_breakpoint (b);
+ break;
+ }
+}
+#endif
+
+/* Tell the user we have just set a breakpoint B. */
+static void
+mention (b)
+ struct breakpoint *b;
+{
+ switch (b->type)
+ {
+ case bp_watchpoint:
+ printf_filtered ("Watchpoint %d: ", b->number);
+ print_expression (b->exp, stdout);
+ break;
+ case bp_breakpoint:
+ printf_filtered ("Breakpoint %d at %s", b->number,
+ local_hex_string((unsigned long) b->address));
+ if (b->source_file)
+ printf_filtered (": file %s, line %d.",
+ b->source_file, b->line_number);
+ break;
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ case bp_step_resume:
+ break;
+ }
+ 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 = 0;
+ resolve_sal_pc (&sal); /* Might error out */
+ describe_other_breakpoints (sal.pc);
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = bp_breakpoint;
+ b->cond = 0;
+ b->addr_string = addr_string;
+ b->enable = enabled;
+ b->disposition = tempflag ? delete : donttouch;
+
+ mention (b);
+}
+#endif /* 0 */
+
+/* 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 = NULL;
+ /* Pointers in arg to the start, and one past the end,
+ of the address part. */
+ char *addr_start = NULL;
+ char *addr_end = NULL;
+ struct cleanup *old_chain;
+ struct cleanup *canonical_strings_chain = NULL;
+ char **canonical = (char **)NULL;
+ int i;
+ int thread;
+
+ 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, &canonical);
+ else
+ sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
+
+ addr_end = arg;
+ }
+
+ if (! sals.nelts)
+ return;
+
+ /* Make sure that all storage allocated in decode_line_1 gets freed in case
+ the following `for' loop errors out. */
+ old_chain = make_cleanup (free, sals.sals);
+ if (canonical != (char **)NULL)
+ {
+ make_cleanup (free, canonical);
+ canonical_strings_chain = make_cleanup (null_cleanup, 0);
+ for (i = 0; i < sals.nelts; i++)
+ {
+ if (canonical[i] != NULL)
+ make_cleanup (free, canonical[i]);
+ }
+ }
+
+ thread = -1; /* No specific thread yet */
+
+ /* Resolve all line numbers to PC's, and verify that conditions
+ can be parsed, before setting any breakpoints. */
+ for (i = 0; i < sals.nelts; i++)
+ {
+ char *tok, *end_tok;
+ int toklen;
+
+ resolve_sal_pc (&sals.sals[i]);
+
+ tok = arg;
+
+ while (tok && *tok)
+ {
+ while (*tok == ' ' || *tok == '\t')
+ tok++;
+
+ end_tok = tok;
+
+ while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
+ end_tok++;
+
+ toklen = end_tok - tok;
+
+ if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
+ {
+ tok = cond_start = end_tok + 1;
+ cond = parse_exp_1 (&tok, block_for_pc (sals.sals[i].pc), 0);
+ cond_end = tok;
+ }
+ else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
+ {
+ char *tmptok;
+
+ tok = end_tok + 1;
+ tmptok = tok;
+ thread = strtol (tok, &tok, 0);
+ if (tok == tmptok)
+ error ("Junk after thread keyword.");
+ if (!valid_thread_id (thread))
+ error ("Unknown thread %d\n", thread);
+ }
+ else
+ error ("Junk at end of arguments.");
+ }
+ }
+
+ /* Remove the canonical strings from the cleanup, they are needed below. */
+ if (canonical != (char **)NULL)
+ discard_cleanups (canonical_strings_chain);
+
+ /* Now set all the breakpoints. */
+ 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->type = bp_breakpoint;
+ b->cond = cond;
+ b->thread = thread;
+
+ /* If a canonical line spec is needed use that instead of the
+ command string. */
+ if (canonical != (char **)NULL && canonical[i] != NULL)
+ b->addr_string = canonical[i];
+ else 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);
+
+ b->enable = enabled;
+ b->disposition = tempflag ? delete : donttouch;
+
+ mention (b);
+ }
+
+ if (sals.nelts > 1)
+ {
+ printf ("Multiple breakpoints were set.\n");
+ printf ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ }
+ do_cleanups (old_chain);
+}
+
+/* Helper function for break_command_1 and disassemble_command. */
+
+void
+resolve_sal_pc (sal)
+ struct symtab_and_line *sal;
+{
+ CORE_ADDR pc;
+
+ 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);
+ sal->pc = pc;
+ }
+}
+
+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);
+}
+
+/* ARGSUSED */
+static void
+watch_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct breakpoint *b;
+ struct symtab_and_line sal;
+ struct expression *exp;
+ struct block *exp_valid_block;
+ struct value *val;
+
+ sal.pc = 0;
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ /* Parse arguments. */
+ innermost_block = NULL;
+ exp = parse_expression (arg);
+ exp_valid_block = innermost_block;
+ val = evaluate_expression (exp);
+ release_value (val);
+ if (VALUE_LAZY (val))
+ value_fetch_lazy (val);
+
+ /* Now set up the breakpoint. */
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = bp_watchpoint;
+ b->disposition = donttouch;
+ b->exp = exp;
+ b->exp_valid_block = exp_valid_block;
+ b->val = val;
+ b->cond = 0;
+ b->cond_string = NULL;
+ b->exp_string = savestring (arg, strlen (arg));
+ mention (b);
+}
+
+/*
+ * Helper routine for the until_command routine in infcmd.c. Here
+ * because it uses the mechanisms of breakpoints.
+ */
+/* ARGSUSED */
+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);
+ struct breakpoint *breakpoint;
+ struct cleanup *old_chain;
+
+ 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, (char ***)NULL);
+ else
+ sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, (char ***)NULL);
+
+ if (sals.nelts != 1)
+ error ("Couldn't get information on specified line.");
+
+ sal = sals.sals[0];
+ free ((PTR)sals.sals); /* malloc'd, so freed */
+
+ if (*arg)
+ error ("Junk at end of arguments.");
+
+ resolve_sal_pc (&sal);
+
+ breakpoint = set_momentary_breakpoint (sal, selected_frame, bp_until);
+
+ old_chain = make_cleanup(delete_breakpoint, breakpoint);
+
+ /* 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;
+ breakpoint = set_momentary_breakpoint (sal, prev_frame, bp_until);
+ make_cleanup(delete_breakpoint, breakpoint);
+ }
+
+ proceed (-1, -1, 0);
+ do_cleanups(old_chain);
+}
+
+#if 0
+/* These aren't used; I don't konw what they were for. */
+/* 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 ()
+{
+}
+#endif /* 0 */
+
+struct sal_chain
+{
+ struct sal_chain *next;
+ struct symtab_and_line sal;
+};
+
+#if 0
+/* This isn't used; I don't know what it was for. */
+/* 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;
+#if 0
+ struct sal_chain *sal_chain = 0;
+#endif
+
+ 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);
+#if 0
+ win:
+#endif
+ p = p1;
+ while (*p == ' ' || *p == '\t') p++;
+ }
+}
+#endif /* 0 */
+
+/* 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;
+{
+ register struct blockvector *bl;
+ register struct block *block;
+ int index, have_default = 0;
+ struct frame_info *fi;
+ CORE_ADDR pc;
+ struct symtabs_and_lines sals;
+ struct sal_chain *sal_chain = 0;
+ char *blocks_searched;
+
+ /* Not sure whether an error message is always the correct response,
+ but it's better than a core dump. */
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+ block = get_frame_block (selected_frame);
+ fi = get_frame_info (selected_frame);
+ pc = fi->pc;
+
+ 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));
+ memset (blocks_searched, 0, 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 (STREQ (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. */
+
+static 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;
+
+ 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 implemented");
+#if 0
+ /* This isn't used; I don't know what it was for. */
+ sals = map_catch_names (arg, catch_breakpoint);
+#endif
+ }
+
+ if (! sals.nelts)
+ return;
+
+ save_arg = arg;
+ for (i = 0; i < sals.nelts; i++)
+ {
+ resolve_sal_pc (&sals.sals[i]);
+
+ while (arg && *arg)
+ {
+ if (arg[0] == 'i' && arg[1] == 'f'
+ && (arg[2] == ' ' || arg[2] == '\t'))
+ cond = parse_exp_1 ((arg += 2, &arg),
+ block_for_pc (sals.sals[i].pc), 0);
+ else
+ error ("Junk at end of arguments.");
+ }
+ arg = save_arg;
+ }
+
+ 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->type = bp_breakpoint;
+ b->cond = cond;
+ b->enable = enabled;
+ b->disposition = tempflag ? delete : donttouch;
+
+ mention (b);
+ }
+
+ if (sals.nelts > 1)
+ {
+ printf ("Multiple breakpoints were set.\n");
+ printf ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ }
+ free ((PTR)sals.sals);
+}
+
+#if 0
+/* These aren't used; I don't know what they were for. */
+/* 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. */
+}
+#endif /* 0 */
+
+static void
+catch_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ catch_command_1 (arg, 0, from_tty);
+}
+
+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->source_file != NULL
+ && sal.symtab != NULL
+ && STREQ (breakpoint_chain->source_file,
+ sal.symtab->filename)
+ && 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->type != bp_watchpoint
+ && (sal.pc
+ ? b->next->address == sal.pc
+ : (b->next->source_file != NULL
+ && sal.symtab != NULL
+ && STREQ (b->next->source_file, sal.symtab->filename)
+ && 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 ((PTR)sals.sals);
+}
+
+/* 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->disposition == delete
+ && bs->stop)
+ delete_breakpoint (bs->breakpoint_at);
+}
+
+/* Delete a breakpoint and clean up all traces of it in the data structures. */
+
+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);
+ /* If this breakpoint was inserted, and there is another breakpoint
+ at the same address, we need to insert the other breakpoint. */
+ if (bpt->inserted)
+ {
+ ALL_BREAKPOINTS (b)
+ if (b->address == bpt->address
+ && !b->duplicate
+ && b->enable != disabled)
+ {
+ int val;
+ val = target_insert_breakpoint (b->address, b->shadow_contents);
+ if (val != 0)
+ {
+ fprintf (stderr, "Cannot insert breakpoint %d:\n", b->number);
+ memory_error (val, b->address); /* which bombs us out */
+ }
+ else
+ b->inserted = 1;
+ }
+ }
+
+ 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 (bpt->exp_string != NULL)
+ free (bpt->exp_string);
+ if (bpt->source_file != NULL)
+ free (bpt->source_file);
+
+ if (xgdb_verbose && bpt->type == bp_breakpoint)
+ 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 ((PTR)bpt);
+}
+
+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);
+}
+
+/* Reset a breakpoint given it's struct breakpoint * BINT.
+ The value we return ends up being the return value from catch_errors.
+ Unused in this case. */
+
+static int
+breakpoint_re_set_one (bint)
+ char *bint;
+{
+ struct breakpoint *b = (struct breakpoint *)bint; /* get past catch_errs */
+ int i;
+ struct symtabs_and_lines sals;
+ char *s;
+ enum enable save_enable;
+
+ switch (b->type)
+ {
+ case bp_breakpoint:
+ if (b->addr_string == NULL)
+ {
+ /* Anything without a string can't be re-set. */
+ delete_breakpoint (b);
+ return 0;
+ }
+ /* In case we have a problem, disable this breakpoint. We'll restore
+ its status if we succeed. */
+ save_enable = b->enable;
+ b->enable = disabled;
+
+ s = b->addr_string;
+ sals = decode_line_1 (&s, 1, (struct symtab *)NULL, 0, (char ***)NULL);
+ for (i = 0; i < sals.nelts; i++)
+ {
+ resolve_sal_pc (&sals.sals[i]);
+
+ /* Reparse conditions, they might contain references to the
+ old symtab. */
+ if (b->cond_string != NULL)
+ {
+ s = b->cond_string;
+ if (b->cond)
+ free ((PTR)b->cond);
+ b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
+ }
+
+ /* We need to re-set the breakpoint if the address changes...*/
+ if (b->address != sals.sals[i].pc
+ /* ...or new and old breakpoints both have source files, and
+ the source file name or the line number changes... */
+ || (b->source_file != NULL
+ && sals.sals[i].symtab != NULL
+ && (!STREQ (b->source_file, sals.sals[i].symtab->filename)
+ || b->line_number != sals.sals[i].line)
+ )
+ /* ...or we switch between having a source file and not having
+ one. */
+ || ((b->source_file == NULL) != (sals.sals[i].symtab == NULL))
+ )
+ {
+ if (b->source_file != NULL)
+ free (b->source_file);
+ if (sals.sals[i].symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file =
+ savestring (sals.sals[i].symtab->filename,
+ strlen (sals.sals[i].symtab->filename));
+ b->line_number = sals.sals[i].line;
+ b->address = sals.sals[i].pc;
+
+ check_duplicates (b->address);
+
+ mention (b);
+ }
+ b->enable = save_enable; /* Restore it, this worked. */
+ }
+ free ((PTR)sals.sals);
+ break;
+
+ case bp_watchpoint:
+ innermost_block = NULL;
+ /* The issue arises of what context to evaluate this in. The same
+ one as when it was set, but what does that mean when symbols have
+ been re-read? We could save the filename and functionname, but
+ if the context is more local than that, the best we could do would
+ be something like how many levels deep and which index at that
+ particular level, but that's going to be less stable than filenames
+ or functionnames. */
+ /* So for now, just use a global context. */
+ b->exp = parse_expression (b->exp_string);
+ b->exp_valid_block = innermost_block;
+ b->val = evaluate_expression (b->exp);
+ release_value (b->val);
+ if (VALUE_LAZY (b->val))
+ value_fetch_lazy (b->val);
+
+ if (b->cond_string != NULL)
+ {
+ s = b->cond_string;
+ b->cond = parse_exp_1 (&s, (struct block *)0, 0);
+ }
+ if (b->enable == enabled)
+ mention (b);
+ break;
+
+ default:
+ printf_filtered ("Deleting unknown breakpoint type %d\n", b->type);
+ /* fall through */
+ case bp_until:
+ case bp_finish:
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ case bp_call_dummy:
+ delete_breakpoint (b);
+ break;
+ }
+
+ return 0;
+}
+
+/* Re-set all breakpoints after symbols have been re-loaded. */
+void
+breakpoint_re_set ()
+{
+ struct breakpoint *b, *temp;
+ static char message1[] = "Error in re-setting breakpoint %d:\n";
+ char message[sizeof (message1) + 30 /* slop */];
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ sprintf (message, message1, b->number); /* Format possible error msg */
+ catch_errors (breakpoint_re_set_one, (char *) b, message,
+ RETURN_MASK_ALL);
+ }
+
+ create_longjmp_breakpoint("longjmp");
+ create_longjmp_breakpoint("_longjmp");
+ create_longjmp_breakpoint("siglongjmp");
+ create_longjmp_breakpoint(NULL);
+
+#if 0
+ /* Took this out (temporaliy at least), since it produces an extra
+ blank line at startup. This messes up the gdbtests. -PB */
+ /* Blank line to finish off all those mention() messages we just printed. */
+ printf_filtered ("\n");
+#endif
+}
+
+/* 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_filtered ("Will stop next time breakpoint %d is reached.",
+ bptnum);
+ else if (count == 1)
+ printf_filtered ("Will ignore next crossing of breakpoint %d.",
+ bptnum);
+ else
+ printf_filtered ("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,
+ longest_to_int (value_as_long (parse_and_eval (p))),
+ from_tty);
+ printf_filtered ("\n");
+}
+
+/* Call FUNCTION on each of the breakpoints
+ whose numbers are given in ARGS. */
+
+static void
+map_breakpoint_numbers (args, function)
+ char *args;
+ void (*function) PARAMS ((struct breakpoint *));
+{
+ 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;
+{
+ FRAME save_selected_frame = NULL;
+ int save_selected_frame_level = -1;
+
+ bpt->enable = enabled;
+
+ if (xgdb_verbose && bpt->type == bp_breakpoint)
+ printf ("breakpoint #%d enabled\n", bpt->number);
+
+ check_duplicates (bpt->address);
+ if (bpt->type == bp_watchpoint)
+ {
+ if (bpt->exp_valid_block != NULL)
+ {
+ FRAME fr = within_scope (bpt->exp_valid_block);
+ if (fr == NULL)
+ {
+ printf_filtered ("\
+Cannot enable watchpoint %d because the block in which its expression\n\
+is valid is not currently in scope.\n", bpt->number);
+ bpt->enable = disabled;
+ return;
+ }
+ save_selected_frame = selected_frame;
+ save_selected_frame_level = selected_frame_level;
+ select_frame (fr, -1);
+ }
+
+ value_free (bpt->val);
+
+ bpt->val = evaluate_expression (bpt->exp);
+ release_value (bpt->val);
+ if (VALUE_LAZY (bpt->val))
+ value_fetch_lazy (bpt->val);
+
+ if (save_selected_frame_level >= 0)
+ select_frame (save_selected_frame, save_selected_frame_level);
+ }
+}
+
+/* ARGSUSED */
+static void
+enable_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct breakpoint *bpt;
+ if (args == 0)
+ ALL_BREAKPOINTS (bpt)
+ switch (bpt->type)
+ {
+ case bp_breakpoint:
+ case bp_watchpoint:
+ enable_breakpoint (bpt);
+ default:
+ continue;
+ }
+ else
+ map_breakpoint_numbers (args, enable_breakpoint);
+}
+
+static void
+disable_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ bpt->enable = disabled;
+
+ if (xgdb_verbose && bpt->type == bp_breakpoint)
+ printf_filtered ("breakpoint #%d disabled\n", bpt->number);
+
+ check_duplicates (bpt->address);
+}
+
+/* ARGSUSED */
+static void
+disable_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register struct breakpoint *bpt;
+ if (args == 0)
+ ALL_BREAKPOINTS (bpt)
+ switch (bpt->type)
+ {
+ case bp_breakpoint:
+ case bp_watchpoint:
+ disable_breakpoint (bpt);
+ default:
+ continue;
+ }
+ else
+ map_breakpoint_numbers (args, disable_breakpoint);
+}
+
+static void
+enable_once_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ bpt->enable = enabled;
+ bpt->disposition = disable;
+
+ check_duplicates (bpt->address);
+}
+
+/* ARGSUSED */
+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 = enabled;
+ bpt->disposition = delete;
+
+ check_duplicates (bpt->address);
+}
+
+/* ARGSUSED */
+static void
+enable_delete_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ map_breakpoint_numbers (args, enable_delete_breakpoint);
+}
+
+/*
+ * 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,
+ (char ***)NULL);
+ else
+ sals = decode_line_1 (&string, funfirstline,
+ (struct symtab *)NULL, 0, (char ***)NULL);
+ if (*string)
+ error ("Junk at end of line specification: %s", string);
+ return sals;
+}
+
+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 an expression to be evaluated whenever\n\
+breakpoint N is reached. ");
+
+ 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_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 user-settable breakpoints, or breakpoint number NUMBER.\n\
+The \"Type\" column indicates one of:\n\
+\tbreakpoint - normal breakpoint\n\
+\twatchpoint - watchpoint\n\
+The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
+the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
+breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
+address and file/line number respectively.\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.");
+
+#if MAINTENANCE_CMDS
+
+ add_cmd ("breakpoints", class_maintenance, maintenance_info_breakpoints,
+ "Status of all breakpoints, or breakpoint number NUMBER.\n\
+The \"Type\" column indicates one of:\n\
+\tbreakpoint - normal breakpoint\n\
+\twatchpoint - watchpoint\n\
+\tlongjmp - internal breakpoint used to step through longjmp()\n\
+\tlongjmp resume - internal breakpoint at the target of longjmp()\n\
+\tuntil - internal breakpoint used by the \"until\" command\n\
+\tfinish - internal breakpoint used by the \"finish\" command\n\
+The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
+the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
+breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
+address and file/line number respectively.\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.",
+ &maintenanceinfolist);
+
+#endif /* MAINTENANCE_CMDS */
+
+ 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", breakpoints_info,
+ "Synonym for ``info breakpoints''.");
+}
+
+/* OK, when we call objfile_relocate, we need to relocate breakpoints
+ too. breakpoint_re_set is not a good choice--for example, if
+ addr_string contains just a line number without a file name the
+ breakpoint might get set in a different file. In general, there is
+ no need to go all the way back to the user's string (though this might
+ work if some effort were made to canonicalize it), since symtabs and
+ everything except addresses are still valid.
+
+ Probably the best way to solve this is to have each breakpoint save
+ the objfile and the section number that was used to set it (if set
+ by "*addr", probably it is best to use find_pc_line to get a symtab
+ and use the objfile and block_line_section for that symtab). Then
+ objfile_relocate can call fixup_breakpoints with the objfile and
+ the new_offsets, and it can relocate only the appropriate breakpoints. */
+
+#ifdef IBM6000_TARGET
+/* But for now, just kludge it based on the concept that before an
+ objfile is relocated the breakpoint is below 0x10000000, and afterwards
+ it is higher, so that way we only relocate each breakpoint once. */
+
+void
+fixup_breakpoints (low, high, delta)
+ CORE_ADDR low;
+ CORE_ADDR high;
+ CORE_ADDR delta;
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ {
+ if (b->address >= low && b->address <= high)
+ b->address += delta;
+ }
+}
+#endif
diff --git a/gnu/usr.bin/gdb/gdb/breakpoint.h b/gnu/usr.bin/gdb/gdb/breakpoint.h
new file mode 100644
index 000000000000..5005450804dc
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/breakpoint.h
@@ -0,0 +1,372 @@
+/* Data structures associated with breakpoints in GDB.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (BREAKPOINT_H)
+#define BREAKPOINT_H 1
+
+#include "frame.h"
+#include "value.h"
+
+/* 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 16
+
+/* Type of breakpoint. */
+/* FIXME In the future, we should fold all other breakpoint-like things into
+ here. This includes:
+
+ * single-step (for machines where we have to simulate single stepping)
+ (probably, though perhaps it is better for it to look as much as
+ possible like a single-step to wait_for_inferior). */
+
+enum bptype {
+ bp_breakpoint, /* Normal breakpoint */
+ bp_until, /* used by until command */
+ bp_finish, /* used by finish command */
+ bp_watchpoint, /* Watchpoint */
+ bp_longjmp, /* secret breakpoint to find longjmp() */
+ bp_longjmp_resume, /* secret breakpoint to escape longjmp() */
+
+ /* Used by wait_for_inferior for stepping over subroutine calls, for
+ stepping over signal handlers, and for skipping prologues. */
+ bp_step_resume,
+
+ /* The breakpoint at the end of a call dummy. */
+ /* FIXME: What if the function we are calling longjmp()s out of the
+ call, or the user gets out with the "return" command? We currently
+ have no way of cleaning up the breakpoint in these (obscure) situations.
+ (Probably can solve this by noticing longjmp, "return", etc., it's
+ similar to noticing when a watchpoint on a local variable goes out
+ of scope (with hardware support for watchpoints)). */
+ bp_call_dummy
+};
+
+/* States of enablement of breakpoint. */
+
+enum enable { disabled, enabled};
+
+/* Disposition of breakpoint. Ie: what to do after hitting it. */
+
+enum bpdisp {
+ delete, /* Delete it */
+ disable, /* Disable it */
+ donttouch /* Leave it alone */
+};
+
+/* Note 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;
+ /* Type of breakpoint. */
+ enum bptype type;
+ /* Zero means disabled; remember the info but don't break here. */
+ enum enable enable;
+ /* What to do with this breakpoint after we hit it. */
+ enum bpdisp disposition;
+ /* 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. Only matters if address is
+ non-NULL. */
+
+ int line_number;
+
+ /* Source file name of this address. Only matters if address is
+ non-NULL. */
+
+ char *source_file;
+
+ /* 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;
+ /* String form of exp (malloc'd), or NULL if none. */
+ char *exp_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;
+ /* Thread number for thread-specific breakpoint, or -1 if don't care */
+ int thread;
+};
+
+/* The following 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 *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. */
+extern void bpstat_clear PARAMS ((bpstat *));
+
+/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
+ is part of the bpstat is copied as well. */
+extern bpstat bpstat_copy PARAMS ((bpstat));
+
+/* FIXME: prototypes uses equivalence between FRAME_ADDR and CORE_ADDR */
+extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, CORE_ADDR, int));
+
+/* This bpstat_what stuff tells wait_for_inferior what to do with a
+ breakpoint (a challenging task). */
+
+enum bpstat_what_main_action {
+ /* Perform various other tests; that is, this bpstat does not
+ say to perform any action (e.g. failed watchpoint and nothing
+ else). */
+ BPSTAT_WHAT_KEEP_CHECKING,
+
+ /* Rather than distinguish between noisy and silent stops here, it
+ might be cleaner to have bpstat_print make that decision (also
+ taking into account stop_print_frame and source_only). But the
+ implications are a bit scary (interaction with auto-displays, etc.),
+ so I won't try it. */
+
+ /* Stop silently. */
+ BPSTAT_WHAT_STOP_SILENT,
+
+ /* Stop and print. */
+ BPSTAT_WHAT_STOP_NOISY,
+
+ /* Remove breakpoints, single step once, then put them back in and
+ go back to what we were doing. It's possible that this should be
+ removed from the main_action and put into a separate field, to more
+ cleanly handle BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE. */
+ BPSTAT_WHAT_SINGLE,
+
+ /* Set longjmp_resume breakpoint, remove all other breakpoints,
+ and continue. The "remove all other breakpoints" part is required
+ if we are also stepping over another breakpoint as well as doing
+ the longjmp handling. */
+ BPSTAT_WHAT_SET_LONGJMP_RESUME,
+
+ /* Clear longjmp_resume breakpoint, then handle as
+ BPSTAT_WHAT_KEEP_CHECKING. */
+ BPSTAT_WHAT_CLEAR_LONGJMP_RESUME,
+
+ /* Clear longjmp_resume breakpoint, then handle as BPSTAT_WHAT_SINGLE. */
+ BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE,
+
+ /* This is just used to keep track of how many enums there are. */
+ BPSTAT_WHAT_LAST
+};
+
+struct bpstat_what {
+ enum bpstat_what_main_action main_action;
+
+ /* Did we hit the step resume breakpoint? This is separate from the
+ main_action to allow for it to be combined with any of the main
+ actions. */
+ int step_resume;
+
+ /* Did we hit a call dummy breakpoint? This only goes with a main_action
+ of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of
+ continuing from a call dummy without popping the frame is not a
+ useful one). */
+ int call_dummy;
+};
+
+/* Tell what to do about this bpstat. */
+struct bpstat_what bpstat_what PARAMS ((bpstat));
+
+/* Find the bpstat associated with a breakpoint. NULL otherwise. */
+bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *));
+
+/* Nonzero if a signal that we got in wait() was due to circumstances
+ explained by the BS. */
+/* Currently that is true if we have hit a breakpoint, or if there is
+ a watchpoint enabled. */
+#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. */
+extern int bpstat_should_step PARAMS ((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). */
+extern int bpstat_print PARAMS ((bpstat));
+
+/* 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. */
+extern int bpstat_num PARAMS ((bpstat *));
+
+/* Perform actions associated with having stopped at *BSP. Actually, we just
+ use this for breakpoint commands. Perhaps other actions will go here
+ later, but this is executed at a late time (from the command loop). */
+extern void bpstat_do_actions PARAMS ((bpstat *));
+
+/* Modify BS so that the actions will not be performed. */
+extern void bpstat_clear_actions PARAMS ((bpstat));
+
+/* Implementation: */
+struct bpstat
+{
+ /* 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 this breakpoint tells us to print the frame. */
+ char print;
+
+ /* Nonzero if this breakpoint tells us to stop. */
+ char stop;
+
+ /* Function called by bpstat_print to print stuff associated with
+ this element of the bpstat chain. Returns 0 or 1 just like
+ bpstat_print, or -1 if it can't deal with it. */
+ int (*print_it) PARAMS((bpstat bs));
+};
+
+/* Prototypes for breakpoint-related functions. */
+
+#ifdef __STDC__ /* Forward declarations for prototypes */
+struct frame_info;
+#endif
+
+extern int
+breakpoint_here_p PARAMS ((CORE_ADDR));
+
+extern int
+breakpoint_thread_match PARAMS ((CORE_ADDR, int));
+
+extern void
+until_break_command PARAMS ((char *, int));
+
+extern void
+breakpoint_re_set PARAMS ((void));
+
+extern void
+clear_momentary_breakpoints PARAMS ((void));
+
+/* FIXME: Prototype uses equivalence of "struct frame_info *" and FRAME */
+extern struct breakpoint *
+set_momentary_breakpoint PARAMS ((struct symtab_and_line,
+ struct frame_info *,
+ enum bptype));
+
+extern void
+set_ignore_count PARAMS ((int, int, int));
+
+extern void
+set_default_breakpoint PARAMS ((int, CORE_ADDR, struct symtab *, int));
+
+extern void
+mark_breakpoints_out PARAMS ((void));
+
+extern void
+breakpoint_init_inferior PARAMS ((void));
+
+extern void
+delete_breakpoint PARAMS ((struct breakpoint *));
+
+extern void
+breakpoint_auto_delete PARAMS ((bpstat));
+
+extern void
+breakpoint_clear_ignore_counts PARAMS ((void));
+
+extern void
+break_command PARAMS ((char *, int));
+
+extern int
+insert_breakpoints PARAMS ((void));
+
+extern int
+remove_breakpoints PARAMS ((void));
+
+extern void
+enable_longjmp_breakpoint PARAMS ((void));
+
+extern void
+disable_longjmp_breakpoint PARAMS ((void));
+
+extern void
+set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR, FRAME));
+
+/* 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 PARAMS ((void));
+
+extern void
+do_displays PARAMS ((void));
+
+extern void
+disable_display PARAMS ((int));
+
+extern void
+clear_displays PARAMS ((void));
+
+#endif /* !defined (BREAKPOINT_H) */
diff --git a/gnu/usr.bin/gdb/gdb/buildsym.c b/gnu/usr.bin/gdb/gdb/buildsym.c
new file mode 100644
index 000000000000..dfa9be131625
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/buildsym.c
@@ -0,0 +1,950 @@
+/* Support routines for building symbol tables in GDB's internal format.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This module provides subroutines used for creating and adding to
+ the symbol table. These routines are called from various symbol-
+ file-reading routines.
+
+ Routines to support specific debugging information formats (stabs,
+ DWARF, etc) belong somewhere else. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "symfile.h" /* Needed for "struct complaint" */
+#include "objfiles.h"
+#include "complaints.h"
+#include <string.h>
+
+/* Ask buildsym.h to define the vars it normally declares `extern'. */
+#define EXTERN /**/
+#include "buildsym.h" /* Our own declarations */
+#undef EXTERN
+
+static int
+compare_line_numbers PARAMS ((const void *, const void *));
+
+static struct blockvector *
+make_blockvector PARAMS ((struct objfile *));
+
+
+/* Initial sizes of data structures. These are realloc'd larger if needed,
+ and realloc'd down to the size actually used, when completed. */
+
+#define INITIAL_CONTEXT_STACK_SIZE 10
+#define INITIAL_LINE_VECTOR_LENGTH 1000
+
+
+/* Complaints about the symbols we have encountered. */
+
+struct complaint innerblock_complaint =
+ {"inner block not inside outer block in %s", 0, 0};
+
+struct complaint innerblock_anon_complaint =
+ {"inner block not inside outer block", 0, 0};
+
+struct complaint blockvector_complaint =
+ {"block at 0x%lx out of order", 0, 0};
+
+
+/* maintain the lists of symbols and blocks */
+
+/* Add a symbol to one of the lists of symbols. */
+
+void
+add_symbol_to_list (symbol, listhead)
+ struct symbol *symbol;
+ struct pending **listhead;
+{
+ register struct pending *link;
+
+ /* 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 == NULL || (*listhead)->nsyms == PENDINGSIZE)
+ {
+ 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;
+}
+
+/* Find a symbol named NAME on a LIST. NAME need not be '\0'-terminated;
+ LENGTH is the length of the name. */
+
+struct symbol *
+find_symbol_in_list (list, name, length)
+ struct pending *list;
+ char *name;
+ int length;
+{
+ int j;
+ char *pp;
+
+ while (list != NULL)
+ {
+ for (j = list->nsyms; --j >= 0; )
+ {
+ pp = SYMBOL_NAME (list->symbol[j]);
+ if (*pp == *name && strncmp (pp, name, length) == 0 &&
+ pp[length] == '\0')
+ {
+ return (list->symbol[j]);
+ }
+ }
+ list = list->next;
+ }
+ return (NULL);
+}
+
+/* At end of reading syms, or in case of quit,
+ really free as many `struct pending's as we can easily find. */
+
+/* ARGSUSED */
+void
+really_free_pendings (foo)
+ int foo;
+{
+ struct pending *next, *next1;
+#if 0
+ struct pending_block *bnext, *bnext1;
+#endif
+
+ for (next = free_pendings; next; next = next1)
+ {
+ next1 = next->next;
+ free ((PTR)next);
+ }
+ free_pendings = NULL;
+
+#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 ((PTR)bnext);
+ }
+#endif
+ pending_blocks = NULL;
+
+ for (next = file_symbols; next != NULL; next = next1)
+ {
+ next1 = next->next;
+ free ((PTR)next);
+ }
+ file_symbols = NULL;
+
+ for (next = global_symbols; next != NULL; next = next1)
+ {
+ next1 = next->next;
+ free ((PTR)next);
+ }
+ global_symbols = NULL;
+}
+
+/* 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. */
+
+void
+finish_block (symbol, listhead, old_blocks, start, end, objfile)
+ struct symbol *symbol;
+ struct pending **listhead;
+ struct pending_block *old_blocks;
+ CORE_ADDR start, end;
+ struct objfile *objfile;
+{
+ register struct pending *next, *next1;
+ register struct block *block;
+ register struct pending_block *pblock;
+ struct pending_block *opblock;
+ register int i;
+ register int j;
+
+ /* 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 (&objfile -> 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)
+ {
+ for (j = next->nsyms - 1; j >= 0; j--)
+ {
+ BLOCK_SYM (block, --i) = next->symbol[j];
+ }
+ }
+
+ BLOCK_START (block) = start;
+ BLOCK_END (block) = end;
+ /* Superblock filled in when containing block is made */
+ BLOCK_SUPERBLOCK (block) = NULL;
+ 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) = NULL;
+ }
+
+ /* 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 = NULL;
+
+ /* Install this block as the superblock
+ of all blocks made since the start of this scope
+ that don't have superblocks yet. */
+
+ opblock = NULL;
+ for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next)
+ {
+ if (BLOCK_SUPERBLOCK (pblock->block) == NULL)
+ {
+#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))
+ {
+ if (symbol)
+ {
+ complain (&innerblock_complaint,
+ SYMBOL_SOURCE_NAME (symbol));
+ }
+ else
+ {
+ complain (&innerblock_anon_complaint);
+ }
+ 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 (&objfile -> 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 (objfile)
+ struct objfile *objfile;
+{
+ 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 (&objfile -> 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 = NULL;
+
+#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,
+ (unsigned long) BLOCK_START(BLOCKVECTOR_BLOCK (blockvector, i)));
+ }
+ }
+ }
+#endif
+
+ return (blockvector);
+}
+
+
+/* Start recording information about source code that came from an included
+ (or otherwise merged-in) source file with a different name. NAME is
+ the name of the file (cannot be NULL), DIRNAME is the directory in which
+ it resides (or NULL if not known). */
+
+void
+start_subfile (name, dirname)
+ char *name;
+ char *dirname;
+{
+ register struct subfile *subfile;
+
+ /* See if this subfile is already known as a subfile of the
+ current main source file. */
+
+ for (subfile = subfiles; subfile; subfile = subfile->next)
+ {
+ if (STREQ (subfile->name, name))
+ {
+ current_subfile = subfile;
+ return;
+ }
+ }
+
+ /* This subfile is not known. Add an entry for it.
+ 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;
+ subfiles = subfile;
+ current_subfile = subfile;
+
+ /* Save its name and compilation directory name */
+ subfile->name = (name == NULL)? NULL : strdup (name);
+ subfile->dirname = (dirname == NULL) ? NULL : strdup (dirname);
+
+ /* Initialize line-number recording for this subfile. */
+ subfile->line_vector = NULL;
+
+ /* Default the source language to whatever can be deduced from
+ the filename. If nothing can be deduced (such as for a C/C++
+ include file with a ".h" extension), then inherit whatever
+ language the previous subfile had. This kludgery is necessary
+ because there is no standard way in some object formats to
+ record the source language. Also, when symtabs are allocated
+ we try to deduce a language then as well, but it is too late
+ for us to use that information while reading symbols, since
+ symtabs aren't allocated until after all the symbols have
+ been processed for a given source file. */
+
+ subfile->language = deduce_language_from_filename (subfile->name);
+ if (subfile->language == language_unknown &&
+ subfile->next != NULL)
+ {
+ subfile->language = subfile->next->language;
+ }
+
+ /* cfront output is a C program, so in most ways it looks like a C
+ program. But to demangle we need to set the language to C++. We
+ can distinguish cfront code by the fact that it has #line
+ directives which specify a file name ending in .C.
+
+ So if the filename of this subfile ends in .C, then change the language
+ of any pending subfiles from C to C++. We also accept any other C++
+ suffixes accepted by deduce_language_from_filename (in particular,
+ some people use .cxx with cfront). */
+
+ if (subfile->name)
+ {
+ struct subfile *s;
+
+ if (deduce_language_from_filename (subfile->name) == language_cplus)
+ for (s = subfiles; s != NULL; s = s->next)
+ if (s->language == language_c)
+ s->language = language_cplus;
+ }
+
+ /* And patch up this file if necessary. */
+ if (subfile->language == language_c
+ && subfile->next != NULL
+ && subfile->next->language == language_cplus)
+ {
+ subfile->language = language_cplus;
+ }
+}
+
+/* For stabs readers, the first N_SO symbol is assumed to be the source
+ file name, and the subfile struct is initialized using that assumption.
+ If another N_SO symbol is later seen, immediately following the first
+ one, then the first one is assumed to be the directory name and the
+ second one is really the source file name.
+
+ So we have to patch up the subfile struct by moving the old name value to
+ dirname and remembering the new name. Some sanity checking is performed
+ to ensure that the state of the subfile struct is reasonable and that the
+ old name we are assuming to be a directory name actually is (by checking
+ for a trailing '/'). */
+
+void
+patch_subfile_names (subfile, name)
+ struct subfile *subfile;
+ char *name;
+{
+ if (subfile != NULL && subfile->dirname == NULL && subfile->name != NULL
+ && subfile->name[strlen(subfile->name)-1] == '/')
+ {
+ subfile->dirname = subfile->name;
+ subfile->name = strdup (name);
+
+ /* Default the source language to whatever can be deduced from
+ the filename. If nothing can be deduced (such as for a C/C++
+ include file with a ".h" extension), then inherit whatever
+ language the previous subfile had. This kludgery is necessary
+ because there is no standard way in some object formats to
+ record the source language. Also, when symtabs are allocated
+ we try to deduce a language then as well, but it is too late
+ for us to use that information while reading symbols, since
+ symtabs aren't allocated until after all the symbols have
+ been processed for a given source file. */
+
+ subfile->language = deduce_language_from_filename (subfile->name);
+ if (subfile->language == language_unknown &&
+ subfile->next != NULL)
+ {
+ subfile->language = subfile->next->language;
+ }
+ }
+}
+
+
+/* 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. */
+
+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 == NULL || current_subfile->name == NULL)
+ {
+ abort ();
+ }
+ tem->name = current_subfile->name;
+}
+
+char *
+pop_subfile ()
+{
+ register char *name;
+ register struct subfile_stack *link = subfile_stack;
+
+ if (link == NULL)
+ {
+ abort ();
+ }
+ name = link->name;
+ subfile_stack = link->next;
+ free ((PTR)link);
+ return (name);
+}
+
+
+/* Add a linetable entry for line number LINE and address PC to the line
+ vector for SUBFILE. */
+
+void
+record_line (subfile, line, pc)
+ register struct subfile *subfile;
+ 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 exists and is big enough. */
+ if (!subfile->line_vector)
+ {
+ subfile->line_vector_length = INITIAL_LINE_VECTOR_LENGTH;
+ subfile->line_vector = (struct linetable *)
+ xmalloc (sizeof (struct linetable)
+ + subfile->line_vector_length * sizeof (struct linetable_entry));
+ subfile->line_vector->nitems = 0;
+ }
+
+ if (subfile->line_vector->nitems + 1 >= subfile->line_vector_length)
+ {
+ subfile->line_vector_length *= 2;
+ subfile->line_vector = (struct linetable *)
+ xrealloc ((char *) subfile->line_vector, (sizeof (struct linetable)
+ + subfile->line_vector_length * sizeof (struct linetable_entry)));
+ }
+
+ e = subfile->line_vector->item + subfile->line_vector->nitems++;
+ e->line = line; e->pc = pc;
+}
+
+
+/* Needed in order to sort line tables from IBM xcoff files. Sigh! */
+
+static int
+compare_line_numbers (ln1p, ln2p)
+ const PTR ln1p;
+ const PTR ln2p;
+{
+ struct linetable_entry *ln1 = (struct linetable_entry *) ln1p;
+ struct linetable_entry *ln2 = (struct linetable_entry *) ln2p;
+
+ /* Note: this code does not assume that CORE_ADDRs can fit in ints.
+ Please keep it that way. */
+ if (ln1->pc < ln2->pc)
+ return -1;
+
+ if (ln1->pc > ln2->pc)
+ return 1;
+
+ /* If pc equal, sort by line. I'm not sure whether this is optimum
+ behavior (see comment at struct linetable in symtab.h). */
+ return ln1->line - ln2->line;
+}
+
+
+/* Start a new symtab for a new source file.
+ Called, for example, when a stabs symbol of type N_SO is seen, or when
+ a DWARF TAG_compile_unit DIE is seen.
+ It indicates the start of data for one original source file. */
+
+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 = NULL;
+ global_symbols = NULL;
+ within_function = 0;
+
+ /* Context stack is initially empty. Allocate first one with room for
+ 10 levels; reuse it forever afterward. */
+ if (context_stack == NULL)
+ {
+ context_stack_size = INITIAL_CONTEXT_STACK_SIZE;
+ context_stack = (struct context_stack *)
+ xmalloc (context_stack_size * sizeof (struct context_stack));
+ }
+ context_stack_depth = 0;
+
+ /* Initialize the list of sub source files with one entry
+ for this file (the top-level source file). */
+
+ subfiles = NULL;
+ current_subfile = NULL;
+ start_subfile (name, dirname);
+}
+
+/* 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.
+ SECTION is the section number (in objfile->section_offsets) of
+ the blockvector and linetable.
+
+ Note that it is possible for end_symtab() to return NULL. In particular,
+ for the DWARF case at least, it will return NULL when it finds a
+ compilation unit that has exactly one DIE, a TAG_compile_unit DIE. This
+ can happen when we link in an object file that was compiled from an empty
+ source file. Returning NULL is probably not the correct thing to do,
+ because then gdb will never know about this empty file (FIXME). */
+
+struct symtab *
+end_symtab (end_addr, sort_pending, sort_linevec, objfile, section)
+ CORE_ADDR end_addr;
+ int sort_pending;
+ int sort_linevec;
+ struct objfile *objfile;
+ int section;
+{
+ register struct symtab *symtab = NULL;
+ register struct blockvector *blockvector;
+ register struct subfile *subfile;
+ register struct context_stack *cstk;
+ struct subfile *nextsub;
+
+ /* Finish the lexical context of the last function in the file;
+ pop the context stack. */
+
+ if (context_stack_depth > 0)
+ {
+ 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, objfile);
+
+ if (context_stack_depth > 0)
+ {
+ /* This is said to happen with SCO. The old coffread.c code
+ simply emptied the context stack, so we do the same. FIXME:
+ Find out why it is happening. This is not believed to happen
+ in most cases (even for coffread.c); it used to be an abort(). */
+ static struct complaint msg =
+ {"Context stack not empty in end_symtab", 0, 0};
+ complain (&msg);
+ context_stack_depth = 0;
+ }
+ }
+
+ /* It is unfortunate that in xcoff, pending blocks might not be ordered
+ in this stage. Especially, blocks for static functions will show up at
+ the end. We need to sort them, so tools like `find_pc_function' and
+ `find_pc_block' can work reliably. */
+
+ if (sort_pending && pending_blocks)
+ {
+ /* FIXME! Remove this horrid bubble sort and use qsort!!! */
+ int swapped;
+ do
+ {
+ struct pending_block *pb, *pbnext;
+
+ pb = pending_blocks;
+ pbnext = pb->next;
+ swapped = 0;
+
+ while (pbnext)
+ {
+ /* swap blocks if unordered! */
+
+ if (BLOCK_START(pb->block) < BLOCK_START(pbnext->block))
+ {
+ struct block *tmp = pb->block;
+ pb->block = pbnext->block;
+ pbnext->block = tmp;
+ swapped = 1;
+ }
+ pb = pbnext;
+ pbnext = pbnext->next;
+ }
+ } while (swapped);
+ }
+
+ /* 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).
+
+ Both cleanup_undefined_types and finish_global_stabs are stabs
+ specific, but harmless for other symbol readers, since on gdb
+ startup or when finished reading stabs, the state is set so these
+ are no-ops. FIXME: Is this handled right in case of QUIT? Can
+ we make this cleaner? */
+
+ cleanup_undefined_types ();
+ finish_global_stabs (objfile);
+
+ if (pending_blocks == NULL
+ && file_symbols == NULL
+ && global_symbols == NULL)
+ {
+ /* Ignore symtabs that have no functions with real debugging info */
+ blockvector = NULL;
+ }
+ else
+ {
+ /* Define the STATIC_BLOCK & GLOBAL_BLOCK, and build the blockvector. */
+ finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr,
+ objfile);
+ finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr,
+ objfile);
+ blockvector = make_blockvector (objfile);
+ }
+
+#ifdef PROCESS_LINENUMBER_HOOK
+ PROCESS_LINENUMBER_HOOK (); /* Needed for xcoff. */
+#endif
+
+ /* Now create the symtab objects proper, one for each subfile. */
+ /* (The main file is the last one on the chain.) */
+
+ for (subfile = subfiles; subfile; subfile = nextsub)
+ {
+ int linetablesize = 0;
+ /* If we have blocks of symbols, make a symtab.
+ Otherwise, just ignore this file and any line number info in it. */
+ symtab = NULL;
+ if (blockvector)
+ {
+ if (subfile->line_vector)
+ {
+ linetablesize = sizeof (struct linetable) +
+ subfile->line_vector->nitems * sizeof (struct linetable_entry);
+#if 0
+ /* I think this is artifact from before it went on the obstack.
+ I doubt we'll need the memory between now and when we
+ free it later in this function. */
+ /* First, shrink the linetable to make more memory. */
+ subfile->line_vector = (struct linetable *)
+ xrealloc ((char *) subfile->line_vector, linetablesize);
+#endif
+ /* If sort_linevec is false, we might want just check to make
+ sure they are sorted and complain() if not, as a way of
+ tracking down compilers/symbol readers which don't get
+ them sorted right. */
+
+ if (sort_linevec)
+ qsort (subfile->line_vector->item,
+ subfile->line_vector->nitems,
+ sizeof (struct linetable_entry), compare_line_numbers);
+ }
+
+ /* Now, allocate a symbol table. */
+ symtab = allocate_symtab (subfile->name, objfile);
+
+ /* Fill in its components. */
+ symtab->blockvector = blockvector;
+ if (subfile->line_vector)
+ {
+ /* Reallocate the line table on the symbol obstack */
+ symtab->linetable = (struct linetable *)
+ obstack_alloc (&objfile -> symbol_obstack, linetablesize);
+ memcpy (symtab->linetable, subfile->line_vector, linetablesize);
+ }
+ else
+ {
+ symtab->linetable = NULL;
+ }
+ symtab->block_line_section = section;
+ if (subfile->dirname)
+ {
+ /* Reallocate the dirname on the symbol obstack */
+ symtab->dirname = (char *)
+ obstack_alloc (&objfile -> symbol_obstack,
+ strlen (subfile -> dirname) + 1);
+ strcpy (symtab->dirname, subfile->dirname);
+ }
+ else
+ {
+ symtab->dirname = NULL;
+ }
+ symtab->free_code = free_linetable;
+ symtab->free_ptr = NULL;
+
+ /* Use whatever language we have been using for this subfile,
+ not the one that was deduced in allocate_symtab from the
+ filename. We already did our own deducing when we created
+ the subfile, and we may have altered our opinion of what
+ language it is from things we found in the symbols. */
+ symtab->language = subfile->language;
+
+ /* All symtabs for the main file and the subfiles share a
+ blockvector, so we need to clear primary for everything but
+ the main file. */
+
+ symtab->primary = 0;
+ }
+ if (subfile->name != NULL)
+ {
+ free ((PTR) subfile->name);
+ }
+ if (subfile->dirname != NULL)
+ {
+ free ((PTR) subfile->dirname);
+ }
+ if (subfile->line_vector != NULL)
+ {
+ free ((PTR) subfile->line_vector);
+ }
+
+ nextsub = subfile->next;
+ free ((PTR)subfile);
+ }
+
+ /* Set this for the main source file. */
+ if (symtab)
+ {
+ symtab->primary = 1;
+ }
+
+ last_source_file = NULL;
+ current_subfile = NULL;
+
+ return (symtab);
+}
+
+
+/* Push a context block. Args are an identifying nesting level (checkable
+ when you pop it), and the starting PC address of this context. */
+
+struct context_stack *
+push_context (desc, valu)
+ int desc;
+ CORE_ADDR valu;
+{
+ register struct context_stack *new;
+
+ if (context_stack_depth == context_stack_size)
+ {
+ context_stack_size *= 2;
+ context_stack = (struct context_stack *)
+ xrealloc ((char *) 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 = NULL;
+
+ local_symbols = NULL;
+
+ return (new);
+}
+
+
+/* Compute a small integer hash code for the given name. */
+
+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);
+}
+
+
+/* Initialize anything that needs initializing when starting to read
+ a fresh piece of a symbol file, e.g. reading in the stuff corresponding
+ to a psymtab. */
+
+void
+buildsym_init ()
+{
+ free_pendings = NULL;
+ file_symbols = NULL;
+ global_symbols = NULL;
+ pending_blocks = NULL;
+}
+
+/* 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
+buildsym_new_init ()
+{
+ buildsym_init ();
+}
+
+/* Initializer for this module */
+
+void
+_initialize_buildsym ()
+{
+}
diff --git a/gnu/usr.bin/gdb/gdb/buildsym.h b/gnu/usr.bin/gdb/gdb/buildsym.h
new file mode 100644
index 000000000000..e034863f396a
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/buildsym.h
@@ -0,0 +1,259 @@
+/* Build symbol tables in GDB's internal format.
+ Copyright (C) 1986-1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (BUILDSYM_H)
+#define BUILDSYM_H 1
+
+/* This module provides definitions used for creating and adding to
+ the symbol table. These routines are called from various symbol-
+ file-reading routines.
+
+ They originated in dbxread.c of gdb-4.2, and were split out to
+ make xcoffread.c more maintainable by sharing code.
+
+ Variables declared in this file can be defined by #define-ing
+ the name EXTERN to null. It is used to declare variables that
+ are normally extern, but which get defined in a single module
+ using this technique. */
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+#define HASHSIZE 127 /* Size of things hashed via hashname() */
+
+/* Name of source file whose symbol data we are now processing.
+ This comes from a symbol of type N_SO. */
+
+EXTERN char *last_source_file;
+
+/* Core address of start of text of current source file.
+ This too comes from the N_SO symbol. */
+
+EXTERN CORE_ADDR last_source_start_addr;
+
+/* 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;
+ enum language language;
+};
+
+EXTERN struct subfile *subfiles;
+
+EXTERN struct subfile *current_subfile;
+
+/* Global variable which, when set, indicates that we are processing a
+ .o file compiled with gcc */
+
+EXTERN unsigned char processing_gcc_compilation;
+
+/* When set, we are processing a .o file compiled by sun acc. This is
+ misnamed; it refers to all stabs-in-elf implementations which use
+ N_UNDF the way Sun does, including Solaris gcc. Hopefully all
+ stabs-in-elf implementations ever invented will choose to be
+ compatible. */
+
+EXTERN unsigned char processing_acc_compilation;
+
+/* Count symbols as they are processed, for error messages. */
+
+EXTERN unsigned int symnum;
+
+/* 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. */
+
+EXTERN struct pending *free_pendings;
+
+/* Here are the three lists that symbols are put on. */
+
+EXTERN struct pending *file_symbols; /* static at top level, and types */
+
+EXTERN struct pending *global_symbols; /* global functions and variables */
+
+EXTERN struct pending *local_symbols; /* everything local to lexic context */
+
+/* Stack representing unclosed lexical contexts
+ (that will become blocks, eventually). */
+
+struct context_stack
+{
+ /* Outer locals at the time we entered */
+
+ struct pending *locals;
+
+ /* Pointer into blocklist as of entry */
+
+ struct pending_block *old_blocks;
+
+ /* Name of function, if any, defining context*/
+
+ struct symbol *name;
+
+ /* PC where this context starts */
+
+ CORE_ADDR start_addr;
+
+ /* Temp slot for exception handling. */
+
+ CORE_ADDR end_addr;
+
+ /* For error-checking matching push/pop */
+
+ int depth;
+
+};
+
+EXTERN struct context_stack *context_stack;
+
+/* Index of first unused entry in context stack. */
+
+EXTERN int context_stack_depth;
+
+/* Currently allocated size of context stack. */
+
+EXTERN int context_stack_size;
+
+/* Macro "function" for popping contexts from the stack. Pushing is done
+ by a real function, push_context. This returns a pointer to a struct
+ context_stack. */
+
+#define pop_context() (&context_stack[--context_stack_depth]);
+
+/* Nonzero if within a function (so symbols should be local,
+ if nothing says specifically). */
+
+EXTERN 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;
+};
+
+EXTERN struct pending_block *pending_blocks;
+
+
+struct subfile_stack
+{
+ struct subfile_stack *next;
+ char *name;
+};
+
+EXTERN struct subfile_stack *subfile_stack;
+
+#define next_symbol_text() (*next_symbol_text_func)()
+
+/* Function to invoke get the next symbol. Return the symbol name. */
+
+EXTERN char *(*next_symbol_text_func) PARAMS ((void));
+
+/* Vector of types defined so far, indexed by their type numbers.
+ Used for both stabs and coff.
+ (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.) */
+
+EXTERN struct type **type_vector;
+
+/* Number of elements allocated for type_vector currently. */
+
+EXTERN int type_vector_length;
+
+/* Initial size of type vector. Is realloc'd larger if needed,
+ and realloc'd down to the size actually used, when completed. */
+
+#define INITIAL_TYPE_VECTOR_LENGTH 160
+
+extern void
+add_symbol_to_list PARAMS ((struct symbol *, struct pending **));
+
+extern struct symbol *
+find_symbol_in_list PARAMS ((struct pending *, char *, int));
+
+extern void
+finish_block PARAMS ((struct symbol *, struct pending **,
+ struct pending_block *, CORE_ADDR, CORE_ADDR,
+ struct objfile *));
+
+extern void
+really_free_pendings PARAMS ((int foo));
+
+extern void
+start_subfile PARAMS ((char *, char *));
+
+extern void
+patch_subfile_names PARAMS ((struct subfile *subfile, char *name));
+
+extern void
+push_subfile PARAMS ((void));
+
+extern char *
+pop_subfile PARAMS ((void));
+
+extern struct symtab *
+end_symtab PARAMS ((CORE_ADDR, int, int, struct objfile *, int));
+
+extern void
+scan_file_globals PARAMS ((struct objfile *));
+
+extern void
+buildsym_new_init PARAMS ((void));
+
+extern void
+buildsym_init PARAMS ((void));
+
+extern struct context_stack *
+push_context PARAMS ((int, CORE_ADDR));
+
+extern void
+record_line PARAMS ((struct subfile *, int, CORE_ADDR));
+
+extern void
+start_symtab PARAMS ((char *, char *, CORE_ADDR));
+
+extern int
+hashname PARAMS ((char *));
+
+#undef EXTERN
+
+#endif /* defined (BUILDSYM_H) */
diff --git a/gnu/usr.bin/gdb/gdb/c-exp.y b/gnu/usr.bin/gdb/gdb/c-exp.y
new file mode 100644
index 000000000000..0e7d39ac6c2f
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/c-exp.y
@@ -0,0 +1,1601 @@
+/* YACC parser for C expressions, for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* 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.
+
+ Note that malloc's and realloc's in this file are transformed to
+ xmalloc and xrealloc respectively by the same sed command in the
+ makefile that remaps any other malloc/realloc inserted by the parser
+ generator. Doing this with #defines and trying to control the interaction
+ with include files (<malloc.h> and <stdlib.h> for example) just became
+ too messy, particularly when such includes can be inserted at random
+ times by the parser generator. */
+
+%{
+
+#include "defs.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "value.h"
+#include "language.h"
+#include "c-lang.h"
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth c_maxdepth
+#define yyparse c_parse
+#define yylex c_lex
+#define yyerror c_error
+#define yylval c_lval
+#define yychar c_char
+#define yydebug c_debug
+#define yypact c_pact
+#define yyr1 c_r1
+#define yyr2 c_r2
+#define yydef c_def
+#define yychk c_chk
+#define yypgo c_pgo
+#define yyact c_act
+#define yyexca c_exca
+#define yyerrflag c_errflag
+#define yynerrs c_nerrs
+#define yyps c_ps
+#define yypv c_pv
+#define yys c_s
+#define yy_yys c_yys
+#define yystate c_state
+#define yytmp c_tmp
+#define yyv c_v
+#define yy_yyv c_yyv
+#define yyval c_val
+#define yylloc c_lloc
+#define yyreds c_reds /* With YYDEBUG defined */
+#define yytoks c_toks /* With YYDEBUG defined */
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+%}
+
+/* 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;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val;
+ 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 gets defined by %union */
+static int
+parse_number PARAMS ((char *, int, int, YYSTYPE *));
+%}
+
+%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
+%type <lval> rcurly
+%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 <typed_val> INT
+%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 defined below to give it higher precedence. */
+%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. */
+
+%token <ssym> NAME_OR_INT
+
+%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
+%token TEMPLATE
+%token ERROR
+
+/* Special type cases, put in to allow the parser to distinguish different
+ legal basetypes. */
+%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
+%token <lval> LAST REGNAME
+
+%token <ivar> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+/* C++ */
+%token THIS
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left OROR
+%left ANDAND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left '<' '>' LEQ GEQ
+%left LSH RSH
+%left '@'
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY INCREMENT DECREMENT
+%right ARROW '.' '[' '('
+%token <ssym> BLOCKNAME
+%type <bval> block
+%left COLONCOLON
+
+
+%%
+
+start : exp1
+ | type_exp
+ ;
+
+type_exp: type
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE);}
+ ;
+
+/* 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_LOGICAL_NOT); }
+ ;
+
+exp : '~' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_COMPLEMENT); }
+ ;
+
+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 qualified_name
+ { /* exp->type::name becomes exp->*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
+ write_exp_elt_opcode (STRUCTOP_MPTR); }
+ ;
+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 '.' qualified_name
+ { /* exp.type::name becomes exp.*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
+ write_exp_elt_opcode (STRUCTOP_MEMBER); }
+ ;
+
+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); }
+ ;
+
+lcurly : '{'
+ { start_arglist (); }
+ ;
+
+arglist :
+ ;
+
+arglist : exp
+ { arglist_len = 1; }
+ ;
+
+arglist : arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+rcurly : '}'
+ { $$ = end_arglist () - 1; }
+ ;
+exp : lcurly arglist rcurly %prec ARROW
+ { write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) $3);
+ write_exp_elt_opcode (OP_ARRAY); }
+ ;
+
+exp : lcurly type rcurly 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_BITWISE_AND); }
+ ;
+
+exp : exp '^' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+ ;
+
+exp : exp '|' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+ ;
+
+exp : exp ANDAND exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+ ;
+
+exp : exp OROR exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_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);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_longcst ((LONGEST)($1.val));
+ 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);
+ write_exp_elt_type (val.typed_val.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val.val);
+ 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
+ { /* C strings are converted into array constants with
+ an explicit null byte added at the end. Thus
+ the array upper bound is the string length.
+ There is no such thing in C as a completely empty
+ string. */
+ char *sp = $1.ptr; int count = $1.length;
+ while (count-- > 0)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST)(*sp++));
+ write_exp_elt_opcode (OP_LONG);
+ }
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST)'\0');
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) ($1.length));
+ write_exp_elt_opcode (OP_ARRAY); }
+ ;
+
+/* 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), STATIC_BLOCK);
+ 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, (int *) NULL,
+ (struct symtab **) 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, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym == 0)
+ error ("No symbol \"%s\" in specified context.",
+ copy_name ($3));
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* block_found is set by lookup_symbol. */
+ write_exp_elt_block (block_found);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); }
+ ;
+
+qualified_name: 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);
+ }
+ | typebase COLONCOLON '~' name
+ {
+ struct type *type = $1;
+ struct stoken tmp_token;
+ 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));
+
+ if (!STREQ (type_name_no_tag (type), $4.ptr))
+ error ("invalid destructor `%s::~%s'",
+ type_name_no_tag (type), $4.ptr);
+
+ tmp_token.ptr = (char*) alloca ($4.length + 2);
+ tmp_token.length = $4.length + 1;
+ tmp_token.ptr[0] = '~';
+ memcpy (tmp_token.ptr+1, $4.ptr, $4.length);
+ tmp_token.ptr[tmp_token.length] = 0;
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (type);
+ write_exp_string (tmp_token);
+ write_exp_elt_opcode (OP_SCOPE);
+ }
+ ;
+
+variable: qualified_name
+ | COLONCOLON name
+ {
+ char *name = copy_name ($2);
+ struct symbol *sym;
+ struct minimal_symbol *msymbol;
+
+ sym =
+ lookup_symbol (name, (const struct block *) NULL,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym)
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+
+ msymbol = lookup_minimal_symbol (name,
+ (struct objfile *) NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_long);
+ write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (msymbol -> type == mst_data ||
+ msymbol -> type == mst_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (msymbol -> type == mst_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 (!have_full_symbols () && !have_partial_symbols ())
+ 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)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
+ 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
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name ($1.stoken);
+
+ msymbol = lookup_minimal_symbol (arg,
+ (struct objfile *) NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_long);
+ write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (msymbol -> type == mst_data ||
+ msymbol -> type == mst_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (msymbol -> type == mst_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 (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name ($1.stoken));
+ }
+ }
+ ;
+
+
+/* shift/reduce conflict: "typebase ." and the token is '('. (Shows up
+ twice, once where qualified_name is a possibility and once where
+ it is not). */
+/* shift/reduce conflict: "typebase CONST_KEYWORD ." and the token is '('. */
+/* shift/reduce conflict: "typebase VOLATILE_KEYWORD ." and the token is
+ '('. */
+ptype : typebase
+ /* "const" and "volatile" are curently ignored. A type qualifier
+ before the type is currently handled in the typebase rule. */
+ | typebase CONST_KEYWORD
+ | typebase VOLATILE_KEYWORD
+ | typebase abs_decl
+ { $$ = follow_types ($1); }
+ | typebase CONST_KEYWORD abs_decl
+ { $$ = follow_types ($1); }
+ | typebase VOLATILE_KEYWORD abs_decl
+ { $$ = follow_types ($1); }
+ ;
+
+abs_decl: '*'
+ { push_type (tp_pointer); $$ = 0; }
+ | '*' abs_decl
+ { push_type (tp_pointer); $$ = $2; }
+ | '&'
+ { push_type (tp_reference); $$ = 0; }
+ | '&' abs_decl
+ { push_type (tp_reference); $$ = $2; }
+ | direct_abs_decl
+ ;
+
+direct_abs_decl: '(' abs_decl ')'
+ { $$ = $2; }
+ | direct_abs_decl array_mod
+ {
+ push_type_int ($2);
+ push_type (tp_array);
+ }
+ | array_mod
+ {
+ push_type_int ($1);
+ push_type (tp_array);
+ $$ = 0;
+ }
+
+ /* shift/reduce conflict. "direct_abs_decl . func_mod", and the token
+ is '('. */
+
+ | direct_abs_decl func_mod
+ { push_type (tp_function); }
+ | func_mod
+ { push_type (tp_function); }
+ ;
+
+array_mod: '[' ']'
+ { $$ = -1; }
+ | '[' INT ']'
+ { $$ = $2.val; }
+ ;
+
+func_mod: '(' ')'
+ { $$ = 0; }
+ | '(' nonempty_typelist ')'
+ { free ((PTR)$2); $$ = 0; }
+ ;
+
+/* shift/reduce conflict: "type '(' typebase COLONCOLON '*' ')' ." and the
+ token is '('. */
+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 ((PTR)$8); }
+ ;
+
+typebase /* Implements (approximately): (type-qualifier)* type-specifier */
+ : 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; }
+ | LONG LONG
+ { $$ = builtin_type_long_long; }
+ | LONG LONG INT_KEYWORD
+ { $$ = builtin_type_long_long; }
+ | UNSIGNED LONG LONG
+ { $$ = builtin_type_unsigned_long_long; }
+ | UNSIGNED LONG LONG INT_KEYWORD
+ { $$ = builtin_type_unsigned_long_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); }
+ | CLASS 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_KEYWORD typename
+ { $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
+ | SIGNED_KEYWORD
+ { $$ = builtin_type_int; }
+ | TEMPLATE name '<' type '>'
+ { $$ = lookup_template_type(copy_name($2), $4,
+ expression_context_block);
+ }
+ /* "const" and "volatile" are curently ignored. A type qualifier
+ after the type is handled in the ptype rule. I think these could
+ be too. */
+ | CONST_KEYWORD typebase { $$ = $2; }
+ | VOLATILE_KEYWORD typebase { $$ = $2; }
+ ;
+
+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 **) malloc (sizeof (struct type *) * 2);
+ $<ivec>$[0] = 1; /* Number of types in vector */
+ $$[1] = $1;
+ }
+ | nonempty_typelist ',' type
+ { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
+ $$ = (struct type **) realloc ((char *) $1, len);
+ $$[$<ivec>$[0]] = $3;
+ }
+ ;
+
+name : NAME { $$ = $1.stoken; }
+ | BLOCKNAME { $$ = $1.stoken; }
+ | TYPENAME { $$ = $1.stoken; }
+ | NAME_OR_INT { $$ = $1.stoken; }
+ ;
+
+name_not_typename : NAME
+ | BLOCKNAME
+/* These would be useful if name_not_typename was useful, but it is just
+ a fake for "variable", so these cause reduce/reduce conflicts because
+ the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
+ =exp) or just an exp. If name_not_typename was ever used in an lvalue
+ context where only a name could occur, this might be useful.
+ | NAME_OR_INT
+ */
+ ;
+
+%%
+
+/* 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 LONGEST prevn = 0;
+ register int i = 0;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+ int long_p = 0;
+ unsigned LONGEST high_bit;
+ struct type *signed_type;
+ struct type *unsigned_type;
+
+ 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')
+ long_p = 1;
+ 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 */
+
+ /* Portably test for overflow (only works for nonzero values, so make
+ a second check for zero). */
+ if((prevn >= n) && n != 0)
+ unsigned_p=1; /* Try something unsigned */
+ /* If range checking enabled, portably test for unsigned overflow. */
+ if(RANGE_CHECK && n!=0)
+ {
+ if((unsigned_p && (unsigned)prevn >= (unsigned)n))
+ range_error("Overflow on numeric constant.");
+ }
+ prevn=n;
+ }
+
+ /* If the number is too big to be an int, or it's got an l suffix
+ then it's a long. Work out if this has to be a long by
+ shifting right and and seeing if anything remains, and the
+ target int size is different to the target long size.
+
+ In the expression below, we could have tested
+ (n >> TARGET_INT_BIT)
+ to see if it was zero,
+ but too many compilers warn about that, when ints and longs
+ are the same size. So we shift it twice, with fewer bits
+ each time, for the same result. */
+
+ if ( (TARGET_INT_BIT != TARGET_LONG_BIT
+ && ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */
+ || long_p)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+
+ putithere->typed_val.val = n;
+
+ /* If the high bit of the worked out type is set then this number
+ has to be unsigned. */
+
+ if (unsigned_p || (n & high_bit))
+ {
+ putithere->typed_val.type = unsigned_type;
+ }
+ else
+ {
+ putithere->typed_val.type = signed_type;
+ }
+
+ return INT;
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static const struct token tokentab3[] =
+ {
+ {">>=", ASSIGN_MODIFY, BINOP_RSH},
+ {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+ };
+
+static const 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_BITWISE_IOR},
+ {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND},
+ {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR},
+ {"++", INCREMENT, BINOP_END},
+ {"--", DECREMENT, BINOP_END},
+ {"->", ARROW, BINOP_END},
+ {"&&", ANDAND, BINOP_END},
+ {"||", OROR, BINOP_END},
+ {"::", COLONCOLON, BINOP_END},
+ {"<<", LSH, BINOP_END},
+ {">>", RSH, BINOP_END},
+ {"==", EQUAL, BINOP_END},
+ {"!=", NOTEQUAL, BINOP_END},
+ {"<=", LEQ, BINOP_END},
+ {">=", GEQ, BINOP_END}
+ };
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ int c;
+ int namelen;
+ unsigned int i;
+ char *tokstart;
+ char *tokptr;
+ int tempbufindex;
+ static char *tempbuf;
+ static int tempbufsize;
+
+ retry:
+
+ tokstart = lexptr;
+ /* See if it is a special token of length 3. */
+ for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+ if (STREQN (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 (STREQN (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 '\'':
+ /* We either have a character constant ('0' or '\177' for example)
+ or we have a quoted symbol reference ('foo(int,int)' in C++
+ for example). */
+ lexptr++;
+ c = *lexptr++;
+ if (c == '\\')
+ c = parse_escape (&lexptr);
+
+ yylval.typed_val.val = c;
+ yylval.typed_val.type = builtin_type_char;
+
+ c = *lexptr++;
+ if (c != '\'')
+ {
+ namelen = skip_quoted (tokstart) - tokstart;
+ if (namelen > 2)
+ {
+ lexptr = tokstart + namelen;
+ if (lexptr[-1] != '\'')
+ error ("Unmatched single quote.");
+ namelen -= 2;
+ tokstart++;
+ goto tryname;
+ }
+ error ("Invalid character constant.");
+ }
+ return INT;
+
+ 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)
+ {
+ /* This test includes !hex because 'e' is a valid hex digit
+ and thus does not indicate a floating point number when
+ the radix is hex. */
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ /* This test does not include !hex, because a '.' always indicates
+ a decimal floating point number regardless of the radix. */
+ else if (!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);
+
+ memcpy (err_copy, tokstart, 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 '"':
+
+ /* Build the gdb internal form of the input string in tempbuf,
+ translating any standard C escape forms seen. Note that the
+ buffer is null byte terminated *only* for the convenience of
+ debugging gdb itself and printing the buffer contents when
+ the buffer contains no embedded nulls. Gdb does not depend
+ upon the buffer being null byte terminated, it uses the length
+ string instead. This allows gdb to handle C strings (as well
+ as strings in other languages) with embedded null bytes */
+
+ tokptr = ++tokstart;
+ tempbufindex = 0;
+
+ do {
+ /* Grow the static temp buffer if necessary, including allocating
+ the first one on demand. */
+ if (tempbufindex + 1 >= tempbufsize)
+ {
+ tempbuf = (char *) realloc (tempbuf, tempbufsize += 64);
+ }
+ switch (*tokptr)
+ {
+ case '\0':
+ case '"':
+ /* Do nothing, loop will terminate. */
+ break;
+ case '\\':
+ tokptr++;
+ c = parse_escape (&tokptr);
+ if (c == -1)
+ {
+ continue;
+ }
+ tempbuf[tempbufindex++] = c;
+ break;
+ default:
+ tempbuf[tempbufindex++] = *tokptr++;
+ break;
+ }
+ } while ((*tokptr != '"') && (*tokptr != '\0'));
+ if (*tokptr++ != '"')
+ {
+ error ("Unterminated string in expression.");
+ }
+ tempbuf[tempbufindex] = '\0'; /* See note above */
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = tokptr;
+ 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. */
+
+ tryname:
+ 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])
+ && STREQN (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)
+ && STREQN (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 (STREQN (tokstart, "unsigned", 8))
+ return UNSIGNED;
+ if (current_language->la_language == language_cplus
+ && STREQN (tokstart, "template", 8))
+ return TEMPLATE;
+ if (STREQN (tokstart, "volatile", 8))
+ return VOLATILE_KEYWORD;
+ break;
+ case 6:
+ if (STREQN (tokstart, "struct", 6))
+ return STRUCT;
+ if (STREQN (tokstart, "signed", 6))
+ return SIGNED_KEYWORD;
+ if (STREQN (tokstart, "sizeof", 6))
+ return SIZEOF;
+ break;
+ case 5:
+ if (current_language->la_language == language_cplus
+ && STREQN (tokstart, "class", 5))
+ return CLASS;
+ if (STREQN (tokstart, "union", 5))
+ return UNION;
+ if (STREQN (tokstart, "short", 5))
+ return SHORT;
+ if (STREQN (tokstart, "const", 5))
+ return CONST_KEYWORD;
+ break;
+ case 4:
+ if (STREQN (tokstart, "enum", 4))
+ return ENUM;
+ if (STREQN (tokstart, "long", 4))
+ return LONG;
+ if (current_language->la_language == language_cplus
+ && STREQN (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, (int *) NULL,
+ (struct symtab **) NULL))
+ return THIS;
+ }
+ break;
+ case 3:
+ if (STREQN (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,
+ current_language->la_language == language_cplus
+ ? &is_a_field_of_this : (int *) NULL,
+ (struct symtab **) 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)
+ {
+ char *p;
+ char *namestart;
+ struct symbol *best_sym;
+
+ /* Look ahead to detect nested types. This probably should be
+ done in the grammar, but trying seemed to introduce a lot
+ of shift/reduce and reduce/reduce conflicts. It's possible
+ that it could be done, though. Or perhaps a non-grammar, but
+ less ad hoc, approach would work well. */
+
+ /* Since we do not currently have any way of distinguishing
+ a nested type from a non-nested one (the stabs don't tell
+ us whether a type is nested), we just ignore the
+ containing type. */
+
+ p = lexptr;
+ best_sym = sym;
+ while (1)
+ {
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ ++p;
+ if (*p == ':' && p[1] == ':')
+ {
+ /* Skip the `::'. */
+ p += 2;
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ ++p;
+ namestart = p;
+ while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
+ || (*p >= 'a' && *p <= 'z')
+ || (*p >= 'A' && *p <= 'Z'))
+ ++p;
+ if (p != namestart)
+ {
+ struct symbol *cur_sym;
+ /* As big as the whole rest of the expression, which is
+ at least big enough. */
+ char *tmp = alloca (strlen (namestart));
+
+ memcpy (tmp, namestart, p - namestart);
+ tmp[p - namestart] = '\0';
+ cur_sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (cur_sym)
+ {
+ if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
+ {
+ best_sym = cur_sym;
+ lexptr = p;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ yylval.tsym.type = SYMBOL_TYPE (best_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;
+ }
+ }
+
+ /* Any other kind of symbol */
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME;
+ }
+}
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error (msg ? msg : "Invalid syntax in expression.");
+}
diff --git a/gnu/usr.bin/gdb/gdb/c-lang.c b/gnu/usr.bin/gdb/gdb/c-lang.c
new file mode 100644
index 000000000000..ea0795915f56
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/c-lang.c
@@ -0,0 +1,447 @@
+/* C language support routines for GDB, the GNU debugger.
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "c-lang.h"
+
+/* Print the character C on STREAM as part of the contents of a literal
+ string whose delimiter is QUOTER. Note that that format for printing
+ characters and strings is language specific. */
+
+static void
+emit_char (c, stream, quoter)
+ register int c;
+ FILE *stream;
+ int quoter;
+{
+
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (c == '\\' || c == quoter)
+ {
+ fputs_filtered ("\\", stream);
+ }
+ fprintf_filtered (stream, "%c", c);
+ }
+ else
+ {
+ 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;
+ }
+ }
+}
+
+static void
+c_printchar (c, stream)
+ int c;
+ FILE *stream;
+{
+ fputs_filtered ("'", stream);
+ emit_char (c, stream, '\'');
+ fputs_filtered ("'", stream);
+}
+
+/* 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. */
+
+static void
+c_printstr (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;
+ extern int repeat_count_threshold;
+ extern int print_max;
+
+ /* If the string was not truncated due to `set print elements', and
+ the last byte of it is a null, we don't print that, in traditional C
+ style. */
+ if ((!force_ellipses) && length > 0 && string[length-1] == '\0')
+ length--;
+
+ 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;
+ }
+ c_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;
+ }
+ emit_char (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);
+}
+
+/* Create a fundamental C type using default reasonable for the current
+ target machine.
+
+ Some object/debugging file formats (DWARF version 1, COFF, etc) do not
+ define fundamental types such as "int" or "double". Others (stabs or
+ DWARF version 2, etc) do define fundamental types. For the formats which
+ don't provide fundamental types, gdb can create such types using this
+ function.
+
+ FIXME: Some compilers distinguish explicitly signed integral types
+ (signed short, signed int, signed long) from "regular" integral types
+ (short, int, long) in the debugging information. There is some dis-
+ agreement as to how useful this feature is. In particular, gcc does
+ not support this. Also, only some debugging formats allow the
+ distinction to be passed on to a debugger. For now, we always just
+ use "short", "int", or "long" as the type name, for both the implicit
+ and explicitly signed types. This also makes life easier for the
+ gdb test suite since we don't have to account for the differences
+ in output depending upon what the compiler and debugging format
+ support. We will probably have to re-examine the issue when gdb
+ starts taking it's fundamental type information directly from the
+ debugging information supplied by the compiler. fnf@cygnus.com */
+
+static struct type *
+c_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type *type = NULL;
+
+ switch (typeid)
+ {
+ default:
+ /* FIXME: For now, if we are asked to produce a type not in this
+ language, create the equivalent of a C integer type with the
+ name "<?type?>". When all the dust settles from the type
+ reconstruction work, this should probably become an error. */
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "<?type?>", objfile);
+ warning ("internal error: no C/C++ fundamental type %d", typeid);
+ break;
+ case FT_VOID:
+ type = init_type (TYPE_CODE_VOID,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "void", objfile);
+ break;
+ case FT_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "char", objfile);
+ break;
+ case FT_SIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "signed char", objfile);
+ break;
+ case FT_UNSIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
+ break;
+ case FT_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "short", objfile);
+ break;
+ case FT_SIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "short", objfile); /* FIXME-fnf */
+ break;
+ case FT_UNSIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
+ break;
+ case FT_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "int", objfile);
+ break;
+ case FT_SIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "int", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
+ break;
+ case FT_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long", objfile);
+ break;
+ case FT_SIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "long", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
+ break;
+ case FT_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long long", objfile);
+ break;
+ case FT_SIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "signed long long", objfile);
+ break;
+ case FT_UNSIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
+ break;
+ case FT_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "float", objfile);
+ break;
+ case FT_DBL_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "double", objfile);
+ break;
+ case FT_EXT_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "long double", objfile);
+ break;
+ }
+ return (type);
+}
+
+
+/* Table mapping opcodes into strings for printing operators
+ and precedences of the operators. */
+
+static const struct op_print c_op_print_tab[] =
+ {
+ {",", BINOP_COMMA, PREC_COMMA, 0},
+ {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+ {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+ {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+ {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+ {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 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_LOGICAL_NOT, PREC_PREFIX, 0},
+ {"~", UNOP_COMPLEMENT, 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},
+ {NULL, 0, 0, 0}
+};
+
+struct type ** const (c_builtin_types[]) =
+{
+ &builtin_type_int,
+ &builtin_type_long,
+ &builtin_type_short,
+ &builtin_type_char,
+ &builtin_type_float,
+ &builtin_type_double,
+ &builtin_type_void,
+ &builtin_type_long_long,
+ &builtin_type_signed_char,
+ &builtin_type_unsigned_char,
+ &builtin_type_unsigned_short,
+ &builtin_type_unsigned_int,
+ &builtin_type_unsigned_long,
+ &builtin_type_unsigned_long_long,
+ &builtin_type_long_double,
+ &builtin_type_complex,
+ &builtin_type_double_complex,
+ 0
+};
+
+const struct language_defn c_language_defn = {
+ "c", /* Language name */
+ language_c,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ c_parse,
+ c_error,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ c_create_fundamental_type, /* Create fundamental type in this language */
+ c_print_type, /* Print a type using appropriate syntax */
+ c_val_print, /* Print a value using appropriate syntax */
+ &BUILTIN_TYPE_LONGEST, /* longest signed integral type */
+ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */
+ &builtin_type_double, /* longest floating point type */ /*FIXME*/
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ c_op_print_tab, /* expression operators for printing */
+ LANG_MAGIC
+};
+
+const struct language_defn cplus_language_defn = {
+ "c++", /* Language name */
+ language_cplus,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ c_parse,
+ c_error,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ c_create_fundamental_type, /* Create fundamental type in this language */
+ c_print_type, /* Print a type using appropriate syntax */
+ c_val_print, /* Print a value using appropriate syntax */
+ &BUILTIN_TYPE_LONGEST, /* longest signed integral type */
+ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */
+ &builtin_type_double, /* longest floating point type */ /*FIXME*/
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ c_op_print_tab, /* expression operators for printing */
+ LANG_MAGIC
+};
+
+void
+_initialize_c_language ()
+{
+ add_language (&c_language_defn);
+ add_language (&cplus_language_defn);
+}
diff --git a/gnu/usr.bin/gdb/gdb/c-lang.h b/gnu/usr.bin/gdb/gdb/c-lang.h
new file mode 100644
index 000000000000..4c343a9a5aa7
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/c-lang.h
@@ -0,0 +1,31 @@
+/* C language support definitions for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern int
+c_parse PARAMS ((void)); /* Defined in c-exp.y */
+
+extern void
+c_error PARAMS ((char *)); /* Defined in c-exp.y */
+
+extern void /* Defined in c-typeprint.c */
+c_print_type PARAMS ((struct type *, char *, FILE *, int, int));
+
+extern int
+c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int,
+ int, enum val_prettyprint));
diff --git a/gnu/usr.bin/gdb/gdb/c-typeprint.c b/gnu/usr.bin/gdb/gdb/c-typeprint.c
new file mode 100644
index 000000000000..fa4035b00ac8
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/c-typeprint.c
@@ -0,0 +1,797 @@
+/* Support for printing C and C++ types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "demangle.h"
+#include "c-lang.h"
+#include "typeprint.h"
+
+#include <string.h>
+#include <errno.h>
+
+extern int demangle; /* whether to print C++ syms raw or source-form */
+
+static void
+c_type_print_args PARAMS ((struct type *, FILE *));
+
+static void
+c_type_print_varspec_suffix PARAMS ((struct type *, FILE *, int, int, int));
+
+static void
+cp_type_print_derivation_info PARAMS ((FILE *, struct type *));
+
+void
+c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int));
+
+void
+c_type_print_base PARAMS ((struct type *, FILE *, int, int));
+
+
+/* Print a description of a type in the format of a
+ typedef for the current language.
+ NEW is the new name for a type TYPE. */
+
+void
+c_typedef_print (type, new, stream)
+ struct type *type;
+ struct symbol *new;
+ FILE *stream;
+{
+ switch (current_language->la_language)
+ {
+#ifdef _LANG_c
+ case language_c:
+ case language_cplus:
+ fprintf_filtered(stream, "typedef ");
+ type_print(type,"",stream,0);
+ if(TYPE_NAME ((SYMBOL_TYPE (new))) == 0
+ || !STREQ (TYPE_NAME ((SYMBOL_TYPE (new))), SYMBOL_NAME (new)))
+ fprintf_filtered(stream, " %s", SYMBOL_SOURCE_NAME(new));
+ break;
+#endif
+#ifdef _LANG_m2
+ case language_m2:
+ fprintf_filtered(stream, "TYPE ");
+ if(!TYPE_NAME(SYMBOL_TYPE(new)) ||
+ !STREQ (TYPE_NAME(SYMBOL_TYPE(new)), SYMBOL_NAME(new)))
+ fprintf_filtered(stream, "%s = ", SYMBOL_SOURCE_NAME(new));
+ else
+ fprintf_filtered(stream, "<builtin> = ");
+ type_print(type,"",stream,0);
+ break;
+#endif
+#ifdef _LANG_chill
+ case language_chill:
+ error ("Missing Chill support in function c_typedef_print."); /*FIXME*/
+#endif
+ default:
+ error("Language not supported.");
+ }
+ fprintf_filtered(stream, ";\n");
+}
+
+
+/* LEVEL is the depth to indent lines by. */
+
+void
+c_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ FILE *stream;
+ int show;
+ int level;
+{
+ register enum type_code code;
+ int demangled_args;
+
+ c_type_print_base (type, stream, show, level);
+ code = TYPE_CODE (type);
+ if ((varstring != NULL && *varstring != '\0')
+ ||
+ /* 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)))
+ fputs_filtered (" ", stream);
+ c_type_print_varspec_prefix (type, stream, show, 0);
+
+ fputs_filtered (varstring, stream);
+
+ /* For demangled function names, we have the arglist as part of the name,
+ so don't print an additional pair of ()'s */
+
+ demangled_args = varstring[strlen(varstring) - 1] == ')';
+ c_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
+
+}
+
+/* Print the C++ method arguments ARGS to the file STREAM. */
+
+void
+cp_type_print_method_args (args, prefix, varstring, staticp, stream)
+ struct type **args;
+ char *prefix;
+ char *varstring;
+ int staticp;
+ FILE *stream;
+{
+ int i;
+
+ fprintf_symbol_filtered (stream, prefix, language_cplus, DMGL_ANSI);
+ fprintf_symbol_filtered (stream, varstring, language_cplus, DMGL_ANSI);
+ 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 only the actual base classes of this type, not the base classes
+ of the base classes. I.E. for the derivation hierarchy:
+
+ class A { int a; };
+ class B : public A {int b; };
+ class C : public B {int c; };
+
+ Print the type of class C as:
+
+ class C : public B {
+ int c;
+ }
+
+ Not as the following (like gdb used to), which is not legal C++ syntax for
+ derived types and may be confused with the multiple inheritance form:
+
+ class C : public B : public A {
+ int c;
+ }
+
+ In general, gdb should try to print the types as closely as possible to
+ the form that they appear in the source code. */
+
+static void
+cp_type_print_derivation_info (stream, type)
+ FILE *stream;
+ struct type *type;
+{
+ char *name;
+ int i;
+
+ for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+ {
+ fputs_filtered (i == 0 ? ": " : ", ", stream);
+ fprintf_filtered (stream, "%s%s ",
+ BASETYPE_VIA_PUBLIC (type, i) ? "public" : "private",
+ BASETYPE_VIA_VIRTUAL(type, i) ? " virtual" : "");
+ name = type_name_no_tag (TYPE_BASECLASS (type, i));
+ fprintf_filtered (stream, "%s", name ? name : "(null)");
+ }
+ if (i > 0)
+ {
+ fputs_filtered (" ", stream);
+ }
+}
+
+/* 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. */
+
+void
+c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int passed_a_ptr;
+{
+ char *name;
+ if (type == 0)
+ return;
+
+ if (TYPE_NAME (type) && show <= 0)
+ return;
+
+ QUIT;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ c_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, "(");
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ fprintf_filtered (stream, " ");
+ name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
+ if (name)
+ fputs_filtered (name, stream);
+ else
+ c_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, "(");
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ {
+ fprintf_filtered (stream, " ");
+ c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
+ fprintf_filtered (stream, "::");
+ }
+ break;
+
+ case TYPE_CODE_REF:
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+ fprintf_filtered (stream, "&");
+ break;
+
+ case TYPE_CODE_FUNC:
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ break;
+
+ case TYPE_CODE_ARRAY:
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ 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:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ /* These types need no prefix. They are listed here so that
+ gcc -Wall will reveal any types that haven't been handled. */
+ break;
+ }
+}
+
+static void
+c_type_print_args (type, stream)
+ struct type *type;
+ FILE *stream;
+{
+ int i;
+ struct type **args;
+
+ fprintf_filtered (stream, "(");
+ args = TYPE_ARG_TYPES (type);
+ if (args != NULL)
+ {
+ if (args[1] == NULL)
+ {
+ fprintf_filtered (stream, "...");
+ }
+ else
+ {
+ for (i = 1;
+ args[i] != NULL && args[i]->code != TYPE_CODE_VOID;
+ i++)
+ {
+ c_print_type (args[i], "", stream, -1, 0);
+ if (args[i+1] == NULL)
+ {
+ fprintf_filtered (stream, "...");
+ }
+ else if (args[i+1]->code != TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream, ",");
+ wrap_here (" ");
+ }
+ }
+ }
+ }
+ fprintf_filtered (stream, ")");
+}
+
+/* Print any array sizes, function arguments or close parentheses
+ needed after the variable name (to describe its type).
+ Args work like c_type_print_varspec_prefix. */
+
+static void
+c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int passed_a_ptr;
+ int demangled_args;
+{
+ 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, "]");
+
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+ break;
+
+ case TYPE_CODE_MEMBER:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+ break;
+
+ case TYPE_CODE_METHOD:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+ if (passed_a_ptr)
+ {
+ c_type_print_args (type, stream);
+ }
+ break;
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0);
+ break;
+
+ case TYPE_CODE_FUNC:
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+ passed_a_ptr, 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ if (!demangled_args)
+ 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:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ /* 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 positive means print details about the type (e.g. enum values),
+ and print structure elements passing SHOW - 1 for show.
+ SHOW zero means just print the type name or struct tag if there is one.
+ If there is no name, print something sensible but concise like
+ "struct {...}".
+ SHOW negative means the same things as SHOW zero. The difference is that
+ zero is used for printing structure elements and -1 is used for the
+ "whatis" command. But I don't see any need to distinguish.
+
+ LEVEL is the number of spaces to indent by.
+ We increase it for some recursive calls. */
+
+void
+c_type_print_base (type, stream, show, level)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int level;
+{
+ register int i;
+ register int len;
+ register int lastval;
+ char *mangled_name;
+ char *demangled_name;
+ enum {s_none, s_public, s_private, s_protected} section_type;
+ QUIT;
+
+ wrap_here (" ");
+ if (type == NULL)
+ {
+ fputs_filtered ("<type unknown>", stream);
+ return;
+ }
+
+ /* When SHOW is zero or less, and there is a valid type name, then always
+ just print the type name directly from the type. */
+ /* If we have "typedef struct foo {. . .} bar;" do we want to print it
+ as "struct foo" or as "bar"? Pick the latter, because C++ folk tend
+ to expect things like "class5 *foo" rather than "struct class5 *foo". */
+
+ if (show <= 0
+ && TYPE_NAME (type) != NULL)
+ {
+ 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:
+ c_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+
+ case TYPE_CODE_STRUCT:
+ if (HAVE_CPLUS_STRUCT (type))
+ {
+ fprintf_filtered (stream, "class ");
+ }
+ else
+ {
+ fprintf_filtered (stream, "struct ");
+ }
+ goto struct_union;
+
+ case TYPE_CODE_UNION:
+ fprintf_filtered (stream, "union ");
+
+ struct_union:
+ if (TYPE_TAG_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_TAG_NAME (type), stream);
+ if (show > 0)
+ fputs_filtered (" ", stream);
+ }
+ wrap_here (" ");
+ if (show <= 0)
+ {
+ /* If we just printed a tag name, no need to print anything else. */
+ if (TYPE_TAG_NAME (type) == NULL)
+ fprintf_filtered (stream, "{...}");
+ }
+ else if (show > 0)
+ {
+ check_stub_type (type);
+
+ cp_type_print_derivation_info (stream, type);
+
+ fprintf_filtered (stream, "{\n");
+ if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
+ {
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
+ else
+ fprintfi_filtered (level + 4, stream, "<no data fields>\n");
+ }
+
+ /* Start off with no specific section type, so we can print
+ one for the first field we find, and use that section type
+ thereafter until we find another type. */
+
+ section_type = s_none;
+
+ /* If there is a base class for this type,
+ do not print the field that it occupies. */
+
+ len = TYPE_NFIELDS (type);
+ 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;
+
+ /* If this is a C++ class we can print the various C++ section
+ labels. */
+
+ if (HAVE_CPLUS_STRUCT (type))
+ {
+ if (TYPE_FIELD_PROTECTED (type, i))
+ {
+ if (section_type != s_protected)
+ {
+ section_type = s_protected;
+ fprintfi_filtered (level + 2, stream,
+ "protected:\n");
+ }
+ }
+ else if (TYPE_FIELD_PRIVATE (type, i))
+ {
+ if (section_type != s_private)
+ {
+ section_type = s_private;
+ fprintfi_filtered (level + 2, stream, "private:\n");
+ }
+ }
+ else
+ {
+ if (section_type != s_public)
+ {
+ section_type = s_public;
+ fprintfi_filtered (level + 2, stream, "public:\n");
+ }
+ }
+ }
+
+ print_spaces_filtered (level + 4, stream);
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ fprintf_filtered (stream, "static ");
+ }
+ c_print_type (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");
+ }
+
+ /* If there are both fields and methods, put a space between. */
+ len = TYPE_NFN_FIELDS (type);
+ if (len && section_type != s_none)
+ fprintf_filtered (stream, "\n");
+
+ /* C++: print out the methods */
+
+ for (i = 0; i < len; i++)
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
+ char *method_name = TYPE_FN_FIELDLIST_NAME (type, i);
+ char *name = type_name_no_tag (type);
+ int is_constructor = name && STREQ(method_name, name);
+ for (j = 0; j < len2; j++)
+ {
+ QUIT;
+ if (TYPE_FN_FIELD_PROTECTED (f, j))
+ {
+ if (section_type != s_protected)
+ {
+ section_type = s_protected;
+ fprintfi_filtered (level + 2, stream,
+ "protected:\n");
+ }
+ }
+ else if (TYPE_FN_FIELD_PRIVATE (f, j))
+ {
+ if (section_type != s_private)
+ {
+ section_type = s_private;
+ fprintfi_filtered (level + 2, stream, "private:\n");
+ }
+ }
+ else
+ {
+ if (section_type != s_public)
+ {
+ section_type = s_public;
+ fprintfi_filtered (level + 2, stream, "public:\n");
+ }
+ }
+
+ 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 ");
+ if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
+ {
+ /* Keep GDB from crashing here. */
+ fprintf (stream, "<undefined type> %s;\n",
+ TYPE_FN_FIELD_PHYSNAME (f, j));
+ break;
+ }
+ else if (!is_constructor)
+ {
+ type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
+ "", stream, 0);
+ fputs_filtered (" ", stream);
+ }
+ if (TYPE_FN_FIELD_STUB (f, j))
+ {
+ /* Build something we can demangle. */
+ mangled_name = gdb_mangle_name (type, i, j);
+ demangled_name =
+ cplus_demangle (mangled_name,
+ DMGL_ANSI | DMGL_PARAMS);
+ if (demangled_name == NULL)
+ fprintf_filtered (stream, "<badly mangled name %s>",
+ mangled_name);
+ else
+ {
+ char *demangled_no_class =
+ strchr (demangled_name, ':');
+
+ if (demangled_no_class == NULL)
+ demangled_no_class = demangled_name;
+ else
+ {
+ if (*++demangled_no_class == ':')
+ ++demangled_no_class;
+ }
+ fputs_filtered (demangled_no_class, stream);
+ free (demangled_name);
+ }
+ free (mangled_name);
+ }
+ else if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
+ && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER)
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j) + 1,
+ "~", method_name, 0, stream);
+ else
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "",
+ method_name,
+ TYPE_FN_FIELD_STATIC_P (f, j),
+ stream);
+
+ fprintf_filtered (stream, ";\n");
+ }
+ }
+
+ fprintfi_filtered (level, stream, "}");
+ }
+ break;
+
+ case TYPE_CODE_ENUM:
+ fprintf_filtered (stream, "enum ");
+ if (TYPE_TAG_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_TAG_NAME (type), stream);
+ if (show > 0)
+ fputs_filtered (" ", stream);
+ }
+
+ wrap_here (" ");
+ if (show <= 0)
+ {
+ /* If we just printed a tag name, no need to print anything else. */
+ if (TYPE_TAG_NAME (type) == NULL)
+ fprintf_filtered (stream, "{...}");
+ }
+ else if (show > 0)
+ {
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ lastval = 0;
+ for (i = 0; i < len; i++)
+ {
+ QUIT;
+ if (i) fprintf_filtered (stream, ", ");
+ wrap_here (" ");
+ 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_VOID:
+ fprintf_filtered (stream, "void");
+ break;
+
+ case TYPE_CODE_UNDEF:
+ fprintf_filtered (stream, "struct <unknown>");
+ break;
+
+ case TYPE_CODE_ERROR:
+ fprintf_filtered (stream, "<unknown type>");
+ break;
+
+ case TYPE_CODE_RANGE:
+ /* This should not occur */
+ fprintf_filtered (stream, "<range type>");
+ break;
+
+ default:
+ /* Handle types not explicitly handled by the other cases,
+ such as fundamental types. For these, just print whatever
+ the type name is, as recorded in the type itself. If there
+ is no type name, then complain. */
+ if (TYPE_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_NAME (type), stream);
+ }
+ else
+ {
+ /* At least for dump_symtab, it is important that this not be
+ an error (). */
+ fprintf_filtered (stream, "<invalid type code %d>",
+ TYPE_CODE (type));
+ }
+ break;
+ }
+}
+
diff --git a/gnu/usr.bin/gdb/gdb/c-valprint.c b/gnu/usr.bin/gdb/gdb/c-valprint.c
new file mode 100644
index 000000000000..bcf0a2876732
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/c-valprint.c
@@ -0,0 +1,416 @@
+/* Support for printing C values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "demangle.h"
+#include "valprint.h"
+#include "language.h"
+
+/* BEGIN-FIXME */
+
+extern int vtblprint; /* Controls printing of vtbl's */
+extern int demangle; /* whether to print C++ syms raw or src-form */
+
+extern void
+cp_print_class_member PARAMS ((char *, struct type *, FILE *, char *));
+
+extern void
+cp_print_class_method PARAMS ((char *, struct type *, FILE *));
+
+extern void
+cp_print_value_fields PARAMS ((struct type *, char *, FILE *, int, int,
+ enum val_prettyprint, struct type **));
+
+extern int
+cp_is_vtbl_ptr_type PARAMS ((struct type *));
+
+extern int
+cp_is_vtbl_member PARAMS ((struct type *));
+
+/* END-FIXME */
+
+
+/* BEGIN-FIXME: Hooks into c-typeprint.c */
+
+extern void
+c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int));
+
+extern void
+cp_type_print_method_args PARAMS ((struct type **, char *, char *, int,
+ FILE *));
+/* END-FIXME */
+
+
+extern struct obstack dont_print_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 string characters
+ printed.
+
+ If DEREF_REF is nonzero, then dereference references, otherwise just print
+ them like pointers.
+
+ The PRETTY parameter controls prettyprinting. */
+
+int
+c_val_print (type, valaddr, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ register unsigned int i = 0; /* Number of characters printed */
+ unsigned len;
+ struct type *elttype;
+ unsigned eltlen;
+ LONGEST val;
+ CORE_ADDR addr;
+
+ 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 (prettyprint_arrays)
+ {
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ /* For an array of chars, print with string syntax. */
+ if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && (format == 0 || format == 's'))
+ {
+ LA_PRINT_STRING (stream, valaddr, len, 0);
+ i = len;
+ }
+ else
+ {
+ fprintf_filtered (stream, "{");
+ /* If this is a virtual function table, print the 0th
+ entry specially, and the rest of the members normally. */
+ if (cp_is_vtbl_ptr_type (elttype))
+ {
+ i = 1;
+ fprintf_filtered (stream, "%d vtable entries", len - 1);
+ }
+ else
+ {
+ i = 0;
+ }
+ val_print_array_elements (type, valaddr, address, stream,
+ format, deref_ref, recurse, pretty, i);
+ fprintf_filtered (stream, "}");
+ }
+ break;
+ }
+ /* Array of unspecified length: treat like pointer to first elt. */
+ addr = address;
+ goto print_unpacked_pointer;
+
+ 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)
+ {
+ cp_print_class_method (valaddr, type, stream);
+ }
+ else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
+ {
+ cp_print_class_member (valaddr,
+ TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
+ stream, "&");
+ }
+ else
+ {
+ addr = unpack_pointer (type, valaddr);
+ print_unpacked_pointer:
+ 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%lx", (unsigned long)addr);
+ }
+
+ /* For a pointer to char or unsigned char, also print the string
+ pointed to, unless pointer is null. */
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && (format == 0 || format == 's')
+ && addr != 0)
+ {
+ i = val_print_string (addr, 0, stream);
+ }
+ else if (cp_is_vtbl_member(type))
+ {
+ /* print vtbl's nicely */
+ CORE_ADDR vt_address = unpack_pointer (type, valaddr);
+
+ struct minimal_symbol *msymbol =
+ lookup_minimal_symbol_by_pc (vt_address);
+ if ((msymbol != NULL) &&
+ (vt_address == SYMBOL_VALUE_ADDRESS (msymbol)))
+ {
+ fputs_filtered (" <", stream);
+ fputs_filtered (SYMBOL_SOURCE_NAME (msymbol), stream);
+ fputs_filtered (">", stream);
+ }
+ if (vtblprint)
+ {
+ value vt_val;
+ struct symbol *wsym = (struct symbol *)NULL;
+ struct type *wtype;
+ struct symtab *s;
+ struct block *block = (struct block *)NULL;
+ int is_this_fld;
+
+
+ wsym = lookup_symbol (SYMBOL_NAME(msymbol), block,
+ VAR_NAMESPACE, &is_this_fld, &s);
+
+ if (wsym)
+ {
+ wtype = SYMBOL_TYPE(wsym);
+ }
+ else
+ {
+ wtype = TYPE_TARGET_TYPE(type);
+ }
+ vt_val = value_at (wtype, vt_address);
+ val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val),
+ VALUE_ADDRESS (vt_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 c_val_print");
+ break;
+
+ case TYPE_CODE_REF:
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
+ {
+ cp_print_class_member (valaddr,
+ TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
+ stream, "");
+ break;
+ }
+ 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 deref_val =
+ value_at
+ (TYPE_TARGET_TYPE (type),
+ unpack_pointer (lookup_pointer_type (builtin_type_void),
+ valaddr));
+ val_print (VALUE_TYPE (deref_val),
+ VALUE_CONTENTS (deref_val),
+ VALUE_ADDRESS (deref_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 && cp_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;
+ }
+ cp_print_value_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 (type, 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
+ {
+ print_longest (stream, 'd', 0, val);
+ }
+ break;
+
+ case TYPE_CODE_FUNC:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ /* FIXME, we should consider, at least for ANSI C language, eliminating
+ the distinction made between FUNCs and POINTERs to FUNCs. */
+ fprintf_filtered (stream, "{");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, "} ");
+ /* Try to print what function it points to, and its address. */
+ print_address_demangle (address, stream, demangle);
+ break;
+
+ case TYPE_CODE_BOOL:
+ /* Do something at least vaguely reasonable, for example if the
+ language is set wrong. */
+
+ case TYPE_CODE_INT:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ val_print_type_code_int (type, valaddr, stream);
+ /* C and C++ has no single byte int type, char is used instead.
+ Since we don't know whether the value is really intended to
+ be used as an integer or a character, print the character
+ equivalent as well. */
+ if (TYPE_LENGTH (type) == 1)
+ {
+ fputs_filtered (" ", stream);
+ LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr),
+ stream);
+ }
+ }
+ break;
+
+ case TYPE_CODE_CHAR:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%u" : "%d",
+ unpack_long (type, valaddr));
+ fputs_filtered (" ", stream);
+ LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), 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_ERROR:
+ fprintf_filtered (stream, "<error type>");
+ break;
+
+ case TYPE_CODE_RANGE:
+ /* FIXME, we should not ever have to print one of these yet. */
+ fprintf_filtered (stream, "<range type>");
+ 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, "<incomplete type>");
+ break;
+
+ default:
+ error ("Invalid C/C++ type code %d in symbol table.", TYPE_CODE (type));
+ }
+ fflush (stream);
+ return (0);
+}
diff --git a/gnu/usr.bin/gdb/gdb/call-cmds.h b/gnu/usr.bin/gdb/gdb/call-cmds.h
new file mode 100644
index 000000000000..9030d8495cfd
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/call-cmds.h
@@ -0,0 +1,28 @@
+/* Prototypes for GDB commands that are called internally by other functions.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern void
+initialize_all_files PARAMS ((void));
+
+extern void
+exec_file_command PARAMS ((char *, int));
+
+extern void
+core_file_command PARAMS ((char *, int));
+
+extern void
+break_command PARAMS ((char *, int));
diff --git a/gnu/usr.bin/gdb/gdb/ch-exp.y b/gnu/usr.bin/gdb/gdb/ch-exp.y
new file mode 100644
index 000000000000..b6370f3241f0
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/ch-exp.y
@@ -0,0 +1,1997 @@
+/* YACC grammar for Chill expressions, for GDB.
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Parse a Chill 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.
+
+ Note that malloc's and realloc's in this file are transformed to
+ xmalloc and xrealloc respectively by the same sed command in the
+ makefile that remaps any other malloc/realloc inserted by the parser
+ generator. Doing this with #defines and trying to control the interaction
+ with include files (<malloc.h> and <stdlib.h> for example) just became
+ too messy, particularly when such includes can be inserted at random
+ times by the parser generator.
+
+ Also note that the language accepted by this parser is more liberal
+ than the one accepted by an actual Chill compiler. For example, the
+ language rule that a simple name string can not be one of the reserved
+ simple name strings is not enforced (e.g "case" is not treated as a
+ reserved name). Another example is that Chill is a strongly typed
+ language, and certain expressions that violate the type constraints
+ may still be evaluated if gdb can do so in a meaningful manner, while
+ such expressions would be rejected by the compiler. The reason for
+ this more liberal behavior is the philosophy that the debugger
+ is intended to be a tool that is used by the programmer when things
+ go wrong, and as such, it should provide as few artificial barriers
+ to it's use as possible. If it can do something meaningful, even
+ something that violates language contraints that are enforced by the
+ compiler, it should do so without complaint.
+
+ */
+
+%{
+
+#include "defs.h"
+#include <ctype.h>
+#include "expression.h"
+#include "language.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "ch-lang.h"
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth chill_maxdepth
+#define yyparse chill_parse
+#define yylex chill_lex
+#define yyerror chill_error
+#define yylval chill_lval
+#define yychar chill_char
+#define yydebug chill_debug
+#define yypact chill_pact
+#define yyr1 chill_r1
+#define yyr2 chill_r2
+#define yydef chill_def
+#define yychk chill_chk
+#define yypgo chill_pgo
+#define yyact chill_act
+#define yyexca chill_exca
+#define yyerrflag chill_errflag
+#define yynerrs chill_nerrs
+#define yyps chill_ps
+#define yypv chill_pv
+#define yys chill_s
+#define yy_yys chill_yys
+#define yystate chill_state
+#define yytmp chill_tmp
+#define yyv chill_v
+#define yy_yyv chill_yyv
+#define yyval chill_val
+#define yylloc chill_lloc
+#define yyreds chill_reds /* With YYDEBUG defined */
+#define yytoks chill_toks /* With YYDEBUG defined */
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+%}
+
+/* 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;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val;
+ 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;
+ }
+
+%token <voidval> FIXME_01
+%token <voidval> FIXME_02
+%token <voidval> FIXME_03
+%token <voidval> FIXME_04
+%token <voidval> FIXME_05
+%token <voidval> FIXME_06
+%token <voidval> FIXME_07
+%token <voidval> FIXME_08
+%token <voidval> FIXME_09
+%token <voidval> FIXME_10
+%token <voidval> FIXME_11
+%token <voidval> FIXME_12
+%token <voidval> FIXME_13
+%token <voidval> FIXME_14
+%token <voidval> FIXME_15
+%token <voidval> FIXME_16
+%token <voidval> FIXME_17
+%token <voidval> FIXME_18
+%token <voidval> FIXME_19
+%token <voidval> FIXME_20
+%token <voidval> FIXME_21
+%token <voidval> FIXME_22
+%token <voidval> FIXME_24
+%token <voidval> FIXME_25
+%token <voidval> FIXME_26
+%token <voidval> FIXME_27
+%token <voidval> FIXME_28
+%token <voidval> FIXME_29
+%token <voidval> FIXME_30
+
+%token <typed_val> INTEGER_LITERAL
+%token <ulval> BOOLEAN_LITERAL
+%token <typed_val> CHARACTER_LITERAL
+%token <dval> FLOAT_LITERAL
+%token <ssym> GENERAL_PROCEDURE_NAME
+%token <ssym> LOCATION_NAME
+%token <voidval> SET_LITERAL
+%token <voidval> EMPTINESS_LITERAL
+%token <sval> CHARACTER_STRING_LITERAL
+%token <sval> BIT_STRING_LITERAL
+%token <tsym> TYPENAME
+%token <sval> FIELD_NAME
+
+%token <voidval> '.'
+%token <voidval> ';'
+%token <voidval> ':'
+%token <voidval> CASE
+%token <voidval> OF
+%token <voidval> ESAC
+%token <voidval> LOGIOR
+%token <voidval> ORIF
+%token <voidval> LOGXOR
+%token <voidval> LOGAND
+%token <voidval> ANDIF
+%token <voidval> '='
+%token <voidval> NOTEQUAL
+%token <voidval> '>'
+%token <voidval> GTR
+%token <voidval> '<'
+%token <voidval> LEQ
+%token <voidval> IN
+%token <voidval> '+'
+%token <voidval> '-'
+%token <voidval> '*'
+%token <voidval> '/'
+%token <voidval> SLASH_SLASH
+%token <voidval> MOD
+%token <voidval> REM
+%token <voidval> NOT
+%token <voidval> POINTER
+%token <voidval> RECEIVE
+%token <voidval> '['
+%token <voidval> ']'
+%token <voidval> '('
+%token <voidval> ')'
+%token <voidval> UP
+%token <voidval> IF
+%token <voidval> THEN
+%token <voidval> ELSE
+%token <voidval> FI
+%token <voidval> ELSIF
+%token <voidval> ILLEGAL_TOKEN
+%token <voidval> NUM
+%token <voidval> PRED
+%token <voidval> SUCC
+%token <voidval> ABS
+%token <voidval> CARD
+%token <voidval> MAX_TOKEN
+%token <voidval> MIN_TOKEN
+%token <voidval> SIZE
+%token <voidval> UPPER
+%token <voidval> LOWER
+%token <voidval> LENGTH
+
+/* Tokens which are not Chill tokens used in expressions, but rather GDB
+ specific things that we recognize in the same context as Chill tokens
+ (register names for example). */
+
+%token <lval> GDB_REGNAME /* Machine register name */
+%token <lval> GDB_LAST /* Value history */
+%token <ivar> GDB_VARIABLE /* Convenience variable */
+%token <voidval> GDB_ASSIGNMENT /* Assign value to somewhere */
+
+%type <voidval> location
+%type <voidval> access_name
+%type <voidval> primitive_value
+%type <voidval> location_contents
+%type <voidval> value_name
+%type <voidval> literal
+%type <voidval> tuple
+%type <voidval> value_string_element
+%type <voidval> value_string_slice
+%type <voidval> value_array_element
+%type <voidval> value_array_slice
+%type <voidval> value_structure_field
+%type <voidval> expression_conversion
+%type <voidval> value_procedure_call
+%type <voidval> value_built_in_routine_call
+%type <voidval> chill_value_built_in_routine_call
+%type <voidval> start_expression
+%type <voidval> zero_adic_operator
+%type <voidval> parenthesised_expression
+%type <voidval> value
+%type <voidval> undefined_value
+%type <voidval> expression
+%type <voidval> conditional_expression
+%type <voidval> then_alternative
+%type <voidval> else_alternative
+%type <voidval> sub_expression
+%type <voidval> value_case_alternative
+%type <voidval> operand_0
+%type <voidval> operand_1
+%type <voidval> operand_2
+%type <voidval> operand_3
+%type <voidval> operand_4
+%type <voidval> operand_5
+%type <voidval> operand_6
+%type <voidval> synonym_name
+%type <voidval> value_enumeration_name
+%type <voidval> value_do_with_name
+%type <voidval> value_receive_name
+%type <voidval> string_primitive_value
+%type <voidval> start_element
+%type <voidval> left_element
+%type <voidval> right_element
+%type <voidval> slice_size
+%type <voidval> array_primitive_value
+%type <voidval> expression_list
+%type <voidval> lower_element
+%type <voidval> upper_element
+%type <voidval> first_element
+%type <voidval> mode_argument
+%type <voidval> upper_lower_argument
+%type <voidval> length_argument
+%type <voidval> array_mode_name
+%type <voidval> string_mode_name
+%type <voidval> variant_structure_mode_name
+%type <voidval> boolean_expression
+%type <voidval> case_selector_list
+%type <voidval> subexpression
+%type <voidval> case_label_specification
+%type <voidval> buffer_location
+%type <voidval> single_assignment_action
+%type <tsym> mode_name
+
+%%
+
+/* Z.200, 5.3.1 */
+
+start : value { }
+ | mode_name
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1.type);
+ write_exp_elt_opcode(OP_TYPE);}
+ ;
+
+value : expression
+ {
+ $$ = 0; /* FIXME */
+ }
+ | undefined_value
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+undefined_value : FIXME_01
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 4.2.1 */
+
+location : access_name
+ | primitive_value POINTER
+ {
+ write_exp_elt_opcode (UNOP_IND);
+ }
+ ;
+
+/* Z.200, 4.2.2 */
+
+access_name : LOCATION_NAME
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym ($1.sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ | GDB_LAST /* gdb specific */
+ {
+ write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ($1);
+ write_exp_elt_opcode (OP_LAST);
+ }
+ | GDB_REGNAME /* gdb specific */
+ {
+ write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst ($1);
+ write_exp_elt_opcode (OP_REGISTER);
+ }
+ | GDB_VARIABLE /* gdb specific */
+ {
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern ($1);
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ }
+ | FIXME_03
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 4.2.8 */
+
+expression_list : expression
+ {
+ arglist_len = 1;
+ }
+ | expression_list ',' expression
+ {
+ arglist_len++;
+ }
+
+/* Z.200, 5.2.1 */
+
+primitive_value : location_contents
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_name
+ {
+ $$ = 0; /* FIXME */
+ }
+ | literal
+ {
+ $$ = 0; /* FIXME */
+ }
+ | tuple
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_string_element
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_string_slice
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_array_element
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_array_slice
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_structure_field
+ {
+ $$ = 0; /* FIXME */
+ }
+ | expression_conversion
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_procedure_call
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_built_in_routine_call
+ {
+ $$ = 0; /* FIXME */
+ }
+ | start_expression
+ {
+ $$ = 0; /* FIXME */
+ }
+ | zero_adic_operator
+ {
+ $$ = 0; /* FIXME */
+ }
+ | parenthesised_expression
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.2.2 */
+
+location_contents: location
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.2.3 */
+
+value_name : synonym_name
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_enumeration_name
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_do_with_name
+ {
+ $$ = 0; /* FIXME */
+ }
+ | value_receive_name
+ {
+ $$ = 0; /* FIXME */
+ }
+ | GENERAL_PROCEDURE_NAME
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym ($1.sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ ;
+
+/* Z.200, 5.2.4.1 */
+
+literal : INTEGER_LITERAL
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_longcst ((LONGEST) ($1.val));
+ write_exp_elt_opcode (OP_LONG);
+ }
+ | BOOLEAN_LITERAL
+ {
+ write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_BOOL);
+ }
+ | CHARACTER_LITERAL
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_longcst ((LONGEST) ($1.val));
+ write_exp_elt_opcode (OP_LONG);
+ }
+ | FLOAT_LITERAL
+ {
+ write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_double);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE);
+ }
+ | SET_LITERAL
+ {
+ $$ = 0; /* FIXME */
+ }
+ | EMPTINESS_LITERAL
+ {
+ $$ = 0; /* FIXME */
+ }
+ | CHARACTER_STRING_LITERAL
+ {
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING);
+ }
+ | BIT_STRING_LITERAL
+ {
+ write_exp_elt_opcode (OP_BITSTRING);
+ write_exp_bitstring ($1);
+ write_exp_elt_opcode (OP_BITSTRING);
+ }
+ ;
+
+/* Z.200, 5.2.5 */
+
+tuple : FIXME_04
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+
+/* Z.200, 5.2.6 */
+
+value_string_element: string_primitive_value '(' start_element ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.2.7 */
+
+value_string_slice: string_primitive_value '(' left_element ':' right_element ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | string_primitive_value '(' start_element UP slice_size ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.2.8 */
+
+value_array_element: array_primitive_value '('
+ /* This is to save the value of arglist_len
+ being accumulated for each dimension. */
+ { start_arglist (); }
+ expression_list ')'
+ {
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ }
+ ;
+
+/* Z.200, 5.2.9 */
+
+value_array_slice: array_primitive_value '(' lower_element ':' upper_element ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | array_primitive_value '(' first_element UP slice_size ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.2.10 */
+
+value_structure_field: primitive_value FIELD_NAME
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($2);
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ }
+ ;
+
+/* Z.200, 5.2.11 */
+
+expression_conversion: mode_name parenthesised_expression
+ {
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_opcode (UNOP_CAST);
+ }
+ ;
+
+/* Z.200, 5.2.12 */
+
+value_procedure_call: FIXME_05
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.2.13 */
+
+value_built_in_routine_call: chill_value_built_in_routine_call
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.2.14 */
+
+start_expression: FIXME_06
+ {
+ $$ = 0; /* FIXME */
+ } /* Not in GNU-Chill */
+ ;
+
+/* Z.200, 5.2.15 */
+
+zero_adic_operator: FIXME_07
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.2.16 */
+
+parenthesised_expression: '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.3.2 */
+
+expression : operand_0
+ {
+ $$ = 0; /* FIXME */
+ }
+ | single_assignment_action
+ {
+ $$ = 0; /* FIXME */
+ }
+ | conditional_expression
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+conditional_expression : IF boolean_expression then_alternative else_alternative FI
+ {
+ $$ = 0; /* FIXME */
+ }
+ | CASE case_selector_list OF value_case_alternative '[' ELSE sub_expression ']' ESAC
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+then_alternative: THEN subexpression
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+else_alternative: ELSE subexpression
+ {
+ $$ = 0; /* FIXME */
+ }
+ | ELSIF boolean_expression then_alternative else_alternative
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+sub_expression : expression
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+value_case_alternative: case_label_specification ':' sub_expression ';'
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.3.3 */
+
+operand_0 : operand_1
+ {
+ $$ = 0; /* FIXME */
+ }
+ | operand_0 LOGIOR operand_1
+ {
+ write_exp_elt_opcode (BINOP_BITWISE_IOR);
+ }
+ | operand_0 ORIF operand_1
+ {
+ $$ = 0; /* FIXME */
+ }
+ | operand_0 LOGXOR operand_1
+ {
+ write_exp_elt_opcode (BINOP_BITWISE_XOR);
+ }
+ ;
+
+/* Z.200, 5.3.4 */
+
+operand_1 : operand_2
+ {
+ $$ = 0; /* FIXME */
+ }
+ | operand_1 LOGAND operand_2
+ {
+ write_exp_elt_opcode (BINOP_BITWISE_AND);
+ }
+ | operand_1 ANDIF operand_2
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 5.3.5 */
+
+operand_2 : operand_3
+ {
+ $$ = 0; /* FIXME */
+ }
+ | operand_2 '=' operand_3
+ {
+ write_exp_elt_opcode (BINOP_EQUAL);
+ }
+ | operand_2 NOTEQUAL operand_3
+ {
+ write_exp_elt_opcode (BINOP_NOTEQUAL);
+ }
+ | operand_2 '>' operand_3
+ {
+ write_exp_elt_opcode (BINOP_GTR);
+ }
+ | operand_2 GTR operand_3
+ {
+ write_exp_elt_opcode (BINOP_GEQ);
+ }
+ | operand_2 '<' operand_3
+ {
+ write_exp_elt_opcode (BINOP_LESS);
+ }
+ | operand_2 LEQ operand_3
+ {
+ write_exp_elt_opcode (BINOP_LEQ);
+ }
+ | operand_2 IN operand_3
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+
+/* Z.200, 5.3.6 */
+
+operand_3 : operand_4
+ {
+ $$ = 0; /* FIXME */
+ }
+ | operand_3 '+' operand_4
+ {
+ write_exp_elt_opcode (BINOP_ADD);
+ }
+ | operand_3 '-' operand_4
+ {
+ write_exp_elt_opcode (BINOP_SUB);
+ }
+ | operand_3 SLASH_SLASH operand_4
+ {
+ write_exp_elt_opcode (BINOP_CONCAT);
+ }
+ ;
+
+/* Z.200, 5.3.7 */
+
+operand_4 : operand_5
+ {
+ $$ = 0; /* FIXME */
+ }
+ | operand_4 '*' operand_5
+ {
+ write_exp_elt_opcode (BINOP_MUL);
+ }
+ | operand_4 '/' operand_5
+ {
+ write_exp_elt_opcode (BINOP_DIV);
+ }
+ | operand_4 MOD operand_5
+ {
+ write_exp_elt_opcode (BINOP_MOD);
+ }
+ | operand_4 REM operand_5
+ {
+ write_exp_elt_opcode (BINOP_REM);
+ }
+ ;
+
+/* Z.200, 5.3.8 */
+
+operand_5 : operand_6
+ {
+ $$ = 0; /* FIXME */
+ }
+ | '-' operand_6
+ {
+ write_exp_elt_opcode (UNOP_NEG);
+ }
+ | NOT operand_6
+ {
+ write_exp_elt_opcode (UNOP_LOGICAL_NOT);
+ }
+ | parenthesised_expression literal
+/* We require the string operand to be a literal, to avoid some
+ nasty parsing ambiguities. */
+ {
+ write_exp_elt_opcode (BINOP_CONCAT);
+ }
+ ;
+
+/* Z.200, 5.3.9 */
+
+operand_6 : POINTER location
+ {
+ write_exp_elt_opcode (UNOP_ADDR);
+ }
+ | RECEIVE buffer_location
+ {
+ $$ = 0; /* FIXME */
+ }
+ | primitive_value
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+
+/* Z.200, 6.2 */
+
+single_assignment_action :
+ location GDB_ASSIGNMENT value
+ {
+ write_exp_elt_opcode (BINOP_ASSIGN);
+ }
+ ;
+
+/* Z.200, 6.20.3 */
+
+chill_value_built_in_routine_call :
+ NUM '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | PRED '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | SUCC '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | ABS '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | CARD '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | MAX_TOKEN '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | MIN_TOKEN '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | SIZE '(' location ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | SIZE '(' mode_argument ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | UPPER '(' upper_lower_argument ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | LOWER '(' upper_lower_argument ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | LENGTH '(' length_argument ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+mode_argument : mode_name
+ {
+ $$ = 0; /* FIXME */
+ }
+ | array_mode_name '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | string_mode_name '(' expression ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ | variant_structure_mode_name '(' expression_list ')'
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+mode_name : TYPENAME
+ ;
+
+upper_lower_argument : expression
+ {
+ $$ = 0; /* FIXME */
+ }
+ | mode_name
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+length_argument : expression
+ {
+ $$ = 0; /* FIXME */
+ }
+ ;
+
+/* Z.200, 12.4.3 */
+
+array_primitive_value : primitive_value
+ {
+ $$ = 0;
+ }
+ ;
+
+
+/* Things which still need productions... */
+
+array_mode_name : FIXME_08 { $$ = 0; }
+string_mode_name : FIXME_09 { $$ = 0; }
+variant_structure_mode_name: FIXME_10 { $$ = 0; }
+synonym_name : FIXME_11 { $$ = 0; }
+value_enumeration_name : FIXME_12 { $$ = 0; }
+value_do_with_name : FIXME_13 { $$ = 0; }
+value_receive_name : FIXME_14 { $$ = 0; }
+string_primitive_value : FIXME_15 { $$ = 0; }
+start_element : FIXME_16 { $$ = 0; }
+left_element : FIXME_17 { $$ = 0; }
+right_element : FIXME_18 { $$ = 0; }
+slice_size : FIXME_19 { $$ = 0; }
+lower_element : FIXME_20 { $$ = 0; }
+upper_element : FIXME_21 { $$ = 0; }
+first_element : FIXME_22 { $$ = 0; }
+boolean_expression : FIXME_26 { $$ = 0; }
+case_selector_list : FIXME_27 { $$ = 0; }
+subexpression : FIXME_28 { $$ = 0; }
+case_label_specification: FIXME_29 { $$ = 0; }
+buffer_location : FIXME_30 { $$ = 0; }
+
+%%
+
+/* Implementation of a dynamically expandable buffer for processing input
+ characters acquired through lexptr and building a value to return in
+ yylval. */
+
+static char *tempbuf; /* Current buffer contents */
+static int tempbufsize; /* Size of allocated buffer */
+static int tempbufindex; /* Current index into buffer */
+
+#define GROWBY_MIN_SIZE 64 /* Minimum amount to grow buffer by */
+
+#define CHECKBUF(size) \
+ do { \
+ if (tempbufindex + (size) >= tempbufsize) \
+ { \
+ growbuf_by_size (size); \
+ } \
+ } while (0);
+
+/* Grow the static temp buffer if necessary, including allocating the first one
+ on demand. */
+
+static void
+growbuf_by_size (count)
+ int count;
+{
+ int growby;
+
+ growby = max (count, GROWBY_MIN_SIZE);
+ tempbufsize += growby;
+ if (tempbuf == NULL)
+ {
+ tempbuf = (char *) malloc (tempbufsize);
+ }
+ else
+ {
+ tempbuf = (char *) realloc (tempbuf, tempbufsize);
+ }
+}
+
+/* Try to consume a simple name string token. If successful, returns
+ a pointer to a nullbyte terminated copy of the name that can be used
+ in symbol table lookups. If not successful, returns NULL. */
+
+static char *
+match_simple_name_string ()
+{
+ char *tokptr = lexptr;
+
+ if (isalpha (*tokptr))
+ {
+ char *result;
+ do {
+ tokptr++;
+ } while (isalnum (*tokptr) || (*tokptr == '_'));
+ yylval.sval.ptr = lexptr;
+ yylval.sval.length = tokptr - lexptr;
+ lexptr = tokptr;
+ result = copy_name (yylval.sval);
+ for (tokptr = result; *tokptr; tokptr++)
+ if (isupper (*tokptr))
+ *tokptr = tolower(*tokptr);
+ return result;
+ }
+ return (NULL);
+}
+
+/* Start looking for a value composed of valid digits as set by the base
+ in use. Note that '_' characters are valid anywhere, in any quantity,
+ and are simply ignored. Since we must find at least one valid digit,
+ or reject this token as an integer literal, we keep track of how many
+ digits we have encountered. */
+
+static int
+decode_integer_value (base, tokptrptr, ivalptr)
+ int base;
+ char **tokptrptr;
+ int *ivalptr;
+{
+ char *tokptr = *tokptrptr;
+ int temp;
+ int digits = 0;
+
+ while (*tokptr != '\0')
+ {
+ temp = tolower (*tokptr);
+ tokptr++;
+ switch (temp)
+ {
+ case '_':
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ temp -= '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ temp -= 'a';
+ temp += 10;
+ break;
+ default:
+ temp = base;
+ break;
+ }
+ if (temp < base)
+ {
+ digits++;
+ *ivalptr *= base;
+ *ivalptr += temp;
+ }
+ else
+ {
+ /* Found something not in domain for current base. */
+ tokptr--; /* Unconsume what gave us indigestion. */
+ break;
+ }
+ }
+
+ /* If we didn't find any digits, then we don't have a valid integer
+ value, so reject the entire token. Otherwise, update the lexical
+ scan pointer, and return non-zero for success. */
+
+ if (digits == 0)
+ {
+ return (0);
+ }
+ else
+ {
+ *tokptrptr = tokptr;
+ return (1);
+ }
+}
+
+static int
+decode_integer_literal (valptr, tokptrptr)
+ int *valptr;
+ char **tokptrptr;
+{
+ char *tokptr = *tokptrptr;
+ int base = 0;
+ int ival = 0;
+ int explicit_base = 0;
+
+ /* Look for an explicit base specifier, which is optional. */
+
+ switch (*tokptr)
+ {
+ case 'd':
+ case 'D':
+ explicit_base++;
+ base = 10;
+ tokptr++;
+ break;
+ case 'b':
+ case 'B':
+ explicit_base++;
+ base = 2;
+ tokptr++;
+ break;
+ case 'h':
+ case 'H':
+ explicit_base++;
+ base = 16;
+ tokptr++;
+ break;
+ case 'o':
+ case 'O':
+ explicit_base++;
+ base = 8;
+ tokptr++;
+ break;
+ default:
+ base = 10;
+ break;
+ }
+
+ /* If we found an explicit base ensure that the character after the
+ explicit base is a single quote. */
+
+ if (explicit_base && (*tokptr++ != '\''))
+ {
+ return (0);
+ }
+
+ /* Attempt to decode whatever follows as an integer value in the
+ indicated base, updating the token pointer in the process and
+ computing the value into ival. Also, if we have an explicit
+ base, then the next character must not be a single quote, or we
+ have a bitstring literal, so reject the entire token in this case.
+ Otherwise, update the lexical scan pointer, and return non-zero
+ for success. */
+
+ if (!decode_integer_value (base, &tokptr, &ival))
+ {
+ return (0);
+ }
+ else if (explicit_base && (*tokptr == '\''))
+ {
+ return (0);
+ }
+ else
+ {
+ *valptr = ival;
+ *tokptrptr = tokptr;
+ return (1);
+ }
+}
+
+/* If it wasn't for the fact that floating point values can contain '_'
+ characters, we could just let strtod do all the hard work by letting it
+ try to consume as much of the current token buffer as possible and
+ find a legal conversion. Unfortunately we need to filter out the '_'
+ characters before calling strtod, which we do by copying the other
+ legal chars to a local buffer to be converted. However since we also
+ need to keep track of where the last unconsumed character in the input
+ buffer is, we have transfer only as many characters as may compose a
+ legal floating point value. */
+
+static int
+match_float_literal ()
+{
+ char *tokptr = lexptr;
+ char *buf;
+ char *copy;
+ double dval;
+ extern double strtod ();
+
+ /* Make local buffer in which to build the string to convert. This is
+ required because underscores are valid in chill floating point numbers
+ but not in the string passed to strtod to convert. The string will be
+ no longer than our input string. */
+
+ copy = buf = (char *) alloca (strlen (tokptr) + 1);
+
+ /* Transfer all leading digits to the conversion buffer, discarding any
+ underscores. */
+
+ while (isdigit (*tokptr) || *tokptr == '_')
+ {
+ if (*tokptr != '_')
+ {
+ *copy++ = *tokptr;
+ }
+ tokptr++;
+ }
+
+ /* Now accept either a '.', or one of [eEdD]. Dot is legal regardless
+ of whether we found any leading digits, and we simply accept it and
+ continue on to look for the fractional part and/or exponent. One of
+ [eEdD] is legal only if we have seen digits, and means that there
+ is no fractional part. If we find neither of these, then this is
+ not a floating point number, so return failure. */
+
+ switch (*tokptr++)
+ {
+ case '.':
+ /* Accept and then look for fractional part and/or exponent. */
+ *copy++ = '.';
+ break;
+
+ case 'e':
+ case 'E':
+ case 'd':
+ case 'D':
+ if (copy == buf)
+ {
+ return (0);
+ }
+ *copy++ = 'e';
+ goto collect_exponent;
+ break;
+
+ default:
+ return (0);
+ break;
+ }
+
+ /* We found a '.', copy any fractional digits to the conversion buffer, up
+ to the first nondigit, non-underscore character. */
+
+ while (isdigit (*tokptr) || *tokptr == '_')
+ {
+ if (*tokptr != '_')
+ {
+ *copy++ = *tokptr;
+ }
+ tokptr++;
+ }
+
+ /* Look for an exponent, which must start with one of [eEdD]. If none
+ is found, jump directly to trying to convert what we have collected
+ so far. */
+
+ switch (*tokptr)
+ {
+ case 'e':
+ case 'E':
+ case 'd':
+ case 'D':
+ *copy++ = 'e';
+ tokptr++;
+ break;
+ default:
+ goto convert_float;
+ break;
+ }
+
+ /* Accept an optional '-' or '+' following one of [eEdD]. */
+
+ collect_exponent:
+ if (*tokptr == '+' || *tokptr == '-')
+ {
+ *copy++ = *tokptr++;
+ }
+
+ /* Now copy an exponent into the conversion buffer. Note that at the
+ moment underscores are *not* allowed in exponents. */
+
+ while (isdigit (*tokptr))
+ {
+ *copy++ = *tokptr++;
+ }
+
+ /* If we transfered any chars to the conversion buffer, try to interpret its
+ contents as a floating point value. If any characters remain, then we
+ must not have a valid floating point string. */
+
+ convert_float:
+ *copy = '\0';
+ if (copy != buf)
+ {
+ dval = strtod (buf, &copy);
+ if (*copy == '\0')
+ {
+ yylval.dval = dval;
+ lexptr = tokptr;
+ return (FLOAT_LITERAL);
+ }
+ }
+ return (0);
+}
+
+/* Recognize a string literal. A string literal is a nonzero sequence
+ of characters enclosed in matching single or double quotes, except that
+ a single character inside single quotes is a character literal, which
+ we reject as a string literal. To embed the terminator character inside
+ a string, it is simply doubled (I.E. "this""is""one""string") */
+
+static int
+match_string_literal ()
+{
+ char *tokptr = lexptr;
+
+ for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
+ {
+ CHECKBUF (1);
+ if (*tokptr == *lexptr)
+ {
+ if (*(tokptr + 1) == *lexptr)
+ {
+ tokptr++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ tempbuf[tempbufindex++] = *tokptr;
+ }
+ if (*tokptr == '\0' /* no terminator */
+ || tempbufindex == 0 /* no string */
+ || (tempbufindex == 1 && *tokptr == '\'')) /* char literal */
+ {
+ return (0);
+ }
+ else
+ {
+ tempbuf[tempbufindex] = '\0';
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = ++tokptr;
+ return (CHARACTER_STRING_LITERAL);
+ }
+}
+
+/* Recognize a character literal. A character literal is single character
+ or a control sequence, enclosed in single quotes. A control sequence
+ is a comma separated list of one or more integer literals, enclosed
+ in parenthesis and introduced with a circumflex character.
+
+ EX: 'a' '^(7)' '^(7,8)'
+
+ As a GNU chill extension, the syntax C'xx' is also recognized as a
+ character literal, where xx is a hex value for the character.
+
+ Note that more than a single character, enclosed in single quotes, is
+ a string literal.
+
+ Also note that the control sequence form is not in GNU Chill since it
+ is ambiguous with the string literal form using single quotes. I.E.
+ is '^(7)' a character literal or a string literal. In theory it it
+ possible to tell by context, but GNU Chill doesn't accept the control
+ sequence form, so neither do we (for now the code is disabled).
+
+ Returns CHARACTER_LITERAL if a match is found.
+ */
+
+static int
+match_character_literal ()
+{
+ char *tokptr = lexptr;
+ int ival = 0;
+
+ if ((tolower (*tokptr) == 'c') && (*(tokptr + 1) == '\''))
+ {
+ /* We have a GNU chill extension form, so skip the leading "C'",
+ decode the hex value, and then ensure that we have a trailing
+ single quote character. */
+ tokptr += 2;
+ if (!decode_integer_value (16, &tokptr, &ival) || (*tokptr != '\''))
+ {
+ return (0);
+ }
+ tokptr++;
+ }
+ else if (*tokptr == '\'')
+ {
+ tokptr++;
+
+ /* Determine which form we have, either a control sequence or the
+ single character form. */
+
+ if ((*tokptr == '^') && (*(tokptr + 1) == '('))
+ {
+#if 0 /* Disable, see note above. -fnf */
+ /* Match and decode a control sequence. Return zero if we don't
+ find a valid integer literal, or if the next unconsumed character
+ after the integer literal is not the trailing ')'.
+ FIXME: We currently don't handle the multiple integer literal
+ form. */
+ tokptr += 2;
+ if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+ {
+ return (0);
+ }
+#else
+ return (0);
+#endif
+ }
+ else
+ {
+ ival = *tokptr++;
+ }
+
+ /* The trailing quote has not yet been consumed. If we don't find
+ it, then we have no match. */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ /* Not a character literal. */
+ return (0);
+ }
+ yylval.typed_val.val = ival;
+ yylval.typed_val.type = builtin_type_chill_char;
+ lexptr = tokptr;
+ return (CHARACTER_LITERAL);
+}
+
+/* Recognize an integer literal, as specified in Z.200 sec 5.2.4.2.
+ Note that according to 5.2.4.2, a single "_" is also a valid integer
+ literal, however GNU-chill requires there to be at least one "digit"
+ in any integer literal. */
+
+static int
+match_integer_literal ()
+{
+ char *tokptr = lexptr;
+ int ival;
+
+ if (!decode_integer_literal (&ival, &tokptr))
+ {
+ return (0);
+ }
+ else
+ {
+ yylval.typed_val.val = ival;
+ yylval.typed_val.type = builtin_type_int;
+ lexptr = tokptr;
+ return (INTEGER_LITERAL);
+ }
+}
+
+/* Recognize a bit-string literal, as specified in Z.200 sec 5.2.4.8
+ Note that according to 5.2.4.8, a single "_" is also a valid bit-string
+ literal, however GNU-chill requires there to be at least one "digit"
+ in any bit-string literal. */
+
+static int
+match_bitstring_literal ()
+{
+ char *tokptr = lexptr;
+ int mask;
+ int bitoffset = 0;
+ int bitcount = 0;
+ int base;
+ int digit;
+
+ tempbufindex = 0;
+
+ /* Look for the required explicit base specifier. */
+
+ switch (*tokptr++)
+ {
+ case 'b':
+ case 'B':
+ base = 2;
+ break;
+ case 'o':
+ case 'O':
+ base = 8;
+ break;
+ case 'h':
+ case 'H':
+ base = 16;
+ break;
+ default:
+ return (0);
+ break;
+ }
+
+ /* Ensure that the character after the explicit base is a single quote. */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+
+ while (*tokptr != '\0' && *tokptr != '\'')
+ {
+ digit = tolower (*tokptr);
+ tokptr++;
+ switch (digit)
+ {
+ case '_':
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ digit -= '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ digit -= 'a';
+ digit += 10;
+ break;
+ default:
+ return (0);
+ break;
+ }
+ if (digit >= base)
+ {
+ /* Found something not in domain for current base. */
+ return (0);
+ }
+ else
+ {
+ /* Extract bits from digit, starting with the msbit appropriate for
+ the current base, and packing them into the bitstring byte,
+ starting at the lsbit. */
+ for (mask = (base >> 1); mask > 0; mask >>= 1)
+ {
+ bitcount++;
+ CHECKBUF (1);
+ if (digit & mask)
+ {
+ tempbuf[tempbufindex] |= (1 << bitoffset);
+ }
+ bitoffset++;
+ if (bitoffset == HOST_CHAR_BIT)
+ {
+ bitoffset = 0;
+ tempbufindex++;
+ }
+ }
+ }
+ }
+
+ /* Verify that we consumed everything up to the trailing single quote,
+ and that we found some bits (IE not just underbars). */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+ else
+ {
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = bitcount;
+ lexptr = tokptr;
+ return (BIT_STRING_LITERAL);
+ }
+}
+
+/* Recognize tokens that start with '$'. These include:
+
+ $regname A native register name or a "standard
+ register name".
+ Return token GDB_REGNAME.
+
+ $variable A convenience variable with a name chosen
+ by the user.
+ Return token GDB_VARIABLE.
+
+ $digits Value history with index <digits>, starting
+ from the first value which has index 1.
+ Return GDB_LAST.
+
+ $$digits Value history with index <digits> relative
+ to the last value. I.E. $$0 is the last
+ value, $$1 is the one previous to that, $$2
+ is the one previous to $$1, etc.
+ Return token GDB_LAST.
+
+ $ | $0 | $$0 The last value in the value history.
+ Return token GDB_LAST.
+
+ $$ An abbreviation for the second to the last
+ value in the value history, I.E. $$1
+ Return token GDB_LAST.
+
+ Note that we currently assume that register names and convenience
+ variables follow the convention of starting with a letter or '_'.
+
+ */
+
+static int
+match_dollar_tokens ()
+{
+ char *tokptr;
+ int regno;
+ int namelength;
+ int negate;
+ int ival;
+
+ /* We will always have a successful match, even if it is just for
+ a single '$', the abbreviation for $$0. So advance lexptr. */
+
+ tokptr = ++lexptr;
+
+ if (*tokptr == '_' || isalpha (*tokptr))
+ {
+ /* Look for a match with a native register name, usually something
+ like "r0" for example. */
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ namelength = strlen (reg_names[regno]);
+ if (STREQN (tokptr, reg_names[regno], namelength)
+ && !isalnum (tokptr[namelength]))
+ {
+ yylval.lval = regno;
+ lexptr += namelength + 1;
+ return (GDB_REGNAME);
+ }
+ }
+
+ /* Look for a match with a standard register name, usually something
+ like "pc", which gdb always recognizes as the program counter
+ regardless of what the native register name is. */
+
+ for (regno = 0; regno < num_std_regs; regno++)
+ {
+ namelength = strlen (std_regs[regno].name);
+ if (STREQN (tokptr, std_regs[regno].name, namelength)
+ && !isalnum (tokptr[namelength]))
+ {
+ yylval.lval = std_regs[regno].regnum;
+ lexptr += namelength;
+ return (GDB_REGNAME);
+ }
+ }
+
+ /* Attempt to match against a convenience variable. Note that
+ this will always succeed, because if no variable of that name
+ already exists, the lookup_internalvar will create one for us.
+ Also note that both lexptr and tokptr currently point to the
+ start of the input string we are trying to match, and that we
+ have already tested the first character for non-numeric, so we
+ don't have to treat it specially. */
+
+ while (*tokptr == '_' || isalnum (*tokptr))
+ {
+ tokptr++;
+ }
+ yylval.sval.ptr = lexptr;
+ yylval.sval.length = tokptr - lexptr;
+ yylval.ivar = lookup_internalvar (copy_name (yylval.sval));
+ lexptr = tokptr;
+ return (GDB_VARIABLE);
+ }
+
+ /* Since we didn't match against a register name or convenience
+ variable, our only choice left is a history value. */
+
+ if (*tokptr == '$')
+ {
+ negate = 1;
+ ival = 1;
+ tokptr++;
+ }
+ else
+ {
+ negate = 0;
+ ival = 0;
+ }
+
+ /* Attempt to decode more characters as an integer value giving
+ the index in the history list. If successful, the value will
+ overwrite ival (currently 0 or 1), and if not, ival will be
+ left alone, which is good since it is currently correct for
+ the '$' or '$$' case. */
+
+ decode_integer_literal (&ival, &tokptr);
+ yylval.lval = negate ? -ival : ival;
+ lexptr = tokptr;
+ return (GDB_LAST);
+}
+
+struct token
+{
+ char *operator;
+ int token;
+};
+
+static const struct token idtokentab[] =
+{
+ { "length", LENGTH },
+ { "lower", LOWER },
+ { "upper", UPPER },
+ { "andif", ANDIF },
+ { "pred", PRED },
+ { "succ", SUCC },
+ { "card", CARD },
+ { "size", SIZE },
+ { "orif", ORIF },
+ { "num", NUM },
+ { "abs", ABS },
+ { "max", MAX_TOKEN },
+ { "min", MIN_TOKEN },
+ { "mod", MOD },
+ { "rem", REM },
+ { "not", NOT },
+ { "xor", LOGXOR },
+ { "and", LOGAND },
+ { "in", IN },
+ { "or", LOGIOR }
+};
+
+static const struct token tokentab2[] =
+{
+ { ":=", GDB_ASSIGNMENT },
+ { "//", SLASH_SLASH },
+ { "->", POINTER },
+ { "/=", NOTEQUAL },
+ { "<=", LEQ },
+ { ">=", GTR }
+};
+
+/* Read one token, getting characters through lexptr. */
+/* This is where we will check to make sure that the language and the
+ operators used are compatible. */
+
+static int
+yylex ()
+{
+ unsigned int i;
+ int token;
+ char *simplename;
+ struct symbol *sym;
+
+ /* Skip over any leading whitespace. */
+ while (isspace (*lexptr))
+ {
+ lexptr++;
+ }
+ /* Look for special single character cases which can't be the first
+ character of some other multicharacter token. */
+ switch (*lexptr)
+ {
+ case '\0':
+ return (0);
+ case ',':
+ case '=':
+ case ';':
+ case '!':
+ case '+':
+ case '*':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ return (*lexptr++);
+ }
+ /* Look for characters which start a particular kind of multicharacter
+ token, such as a character literal, register name, convenience
+ variable name, string literal, etc. */
+ switch (*lexptr)
+ {
+ case '\'':
+ case '\"':
+ /* First try to match a string literal, which is any nonzero
+ sequence of characters enclosed in matching single or double
+ quotes, except that a single character inside single quotes
+ is a character literal, so we have to catch that case also. */
+ token = match_string_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ if (*lexptr == '\'')
+ {
+ token = match_character_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ }
+ break;
+ case 'C':
+ case 'c':
+ token = match_character_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ break;
+ case '$':
+ token = match_dollar_tokens ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ break;
+ }
+ /* See if it is a special token of length 2. */
+ for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++)
+ {
+ if (STREQN (lexptr, tokentab2[i].operator, 2))
+ {
+ lexptr += 2;
+ return (tokentab2[i].token);
+ }
+ }
+ /* Look for single character cases which which could be the first
+ character of some other multicharacter token, but aren't, or we
+ would already have found it. */
+ switch (*lexptr)
+ {
+ case '-':
+ case ':':
+ case '/':
+ case '<':
+ case '>':
+ return (*lexptr++);
+ }
+ /* Look for a float literal before looking for an integer literal, so
+ we match as much of the input stream as possible. */
+ token = match_float_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ token = match_bitstring_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ token = match_integer_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+
+ /* Try to match a simple name string, and if a match is found, then
+ further classify what sort of name it is and return an appropriate
+ token. Note that attempting to match a simple name string consumes
+ the token from lexptr, so we can't back out if we later find that
+ we can't classify what sort of name it is. */
+
+ simplename = match_simple_name_string ();
+
+ if (simplename != NULL)
+ {
+ /* See if it is a reserved identifier. */
+ for (i = 0; i < sizeof (idtokentab) / sizeof (idtokentab[0]); i++)
+ {
+ if (STREQ (simplename, idtokentab[i].operator))
+ {
+ return (idtokentab[i].token);
+ }
+ }
+
+ /* Look for other special tokens. */
+ if (STREQ (simplename, "true"))
+ {
+ yylval.ulval = 1;
+ return (BOOLEAN_LITERAL);
+ }
+ if (STREQ (simplename, "false"))
+ {
+ yylval.ulval = 0;
+ return (BOOLEAN_LITERAL);
+ }
+
+ sym = lookup_symbol (simplename, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym != NULL)
+ {
+ yylval.ssym.stoken.ptr = NULL;
+ yylval.ssym.stoken.length = 0;
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = 0; /* FIXME, C++'ism */
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_BLOCK:
+ /* Found a procedure name. */
+ return (GENERAL_PROCEDURE_NAME);
+ case LOC_STATIC:
+ /* Found a global or local static variable. */
+ return (LOCATION_NAME);
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ if (innermost_block == NULL
+ || contained_in (block_found, innermost_block))
+ {
+ innermost_block = block_found;
+ }
+ return (LOCATION_NAME);
+ break;
+ case LOC_CONST:
+ case LOC_LABEL:
+ return (LOCATION_NAME);
+ break;
+ case LOC_TYPEDEF:
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ case LOC_UNDEF:
+ case LOC_CONST_BYTES:
+ case LOC_OPTIMIZED_OUT:
+ error ("Symbol \"%s\" names no location.", simplename);
+ break;
+ }
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ {
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ }
+ else
+ {
+ error ("No symbol \"%s\" in current context.", simplename);
+ }
+ }
+
+ /* Catch single character tokens which are not part of some
+ longer token. */
+
+ switch (*lexptr)
+ {
+ case '.': /* Not float for example. */
+ lexptr++;
+ while (isspace (*lexptr)) lexptr++;
+ simplename = match_simple_name_string ();
+ if (!simplename)
+ return '.';
+ return FIELD_NAME;
+ }
+
+ return (ILLEGAL_TOKEN);
+}
+
+void
+yyerror (msg)
+ char *msg; /* unused */
+{
+ printf ("Parsing: %s\n", lexptr);
+ if (yychar < 256)
+ {
+ error ("Invalid syntax in expression near character '%c'.", yychar);
+ }
+ else
+ {
+ error ("Invalid syntax in expression");
+ }
+}
diff --git a/gnu/usr.bin/gdb/gdb/ch-lang.c b/gnu/usr.bin/gdb/gdb/ch-lang.c
new file mode 100644
index 000000000000..2f7406103d0c
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/ch-lang.c
@@ -0,0 +1,341 @@
+/* Chill language support routines for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "ch-lang.h"
+
+
+/* For now, Chill uses a simple mangling algorithm whereby you simply
+ discard everything after the occurance of two successive CPLUS_MARKER
+ characters to derive the demangled form. */
+
+char *
+chill_demangle (mangled)
+ const char *mangled;
+{
+ char *joiner;
+ char *demangled;
+
+ joiner = strchr (mangled, CPLUS_MARKER);
+ if (joiner != NULL && *(joiner + 1) == CPLUS_MARKER)
+ {
+ demangled = savestring (mangled, joiner - mangled);
+ }
+ else
+ {
+ demangled = NULL;
+ }
+ return (demangled);
+}
+
+static void
+chill_printchar (c, stream)
+ register int c;
+ FILE *stream;
+{
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (PRINT_LITERAL_FORM (c))
+ {
+ fprintf_filtered (stream, "'%c'", c);
+ }
+ else
+ {
+ fprintf_filtered (stream, "C'%.2x'", (unsigned int) c);
+ }
+}
+
+/* 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.
+ Note that gdb maintains the length of strings without counting the
+ terminating null byte, while chill strings are typically written with
+ an explicit null byte. So we always assume an implied null byte
+ until gdb is able to maintain non-null terminated strings as well
+ as null terminated strings (FIXME).
+ */
+
+static void
+chill_printstr (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_literal_form = 0;
+ int in_control_form = 0;
+ int need_slashslash = 0;
+ unsigned int c;
+ extern int repeat_count_threshold;
+ extern int print_max;
+
+ if (length == 0)
+ {
+ chill_printchar ('\0', stream);
+ 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_slashslash)
+ {
+ fputs_filtered ("//", stream);
+ need_slashslash = 0;
+ }
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < length && string[rep1] == string[i])
+ {
+ ++rep1;
+ ++reps;
+ }
+
+ c = string[i];
+ if (reps > repeat_count_threshold)
+ {
+ if (in_control_form || in_literal_form)
+ {
+ fputs_filtered ("'//", stream);
+ in_control_form = in_literal_form = 0;
+ }
+ chill_printchar (c, stream);
+ fprintf_filtered (stream, "<repeats %u times>", reps);
+ i = rep1 - 1;
+ things_printed += repeat_count_threshold;
+ need_slashslash = 1;
+ }
+ else
+ {
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (!in_literal_form)
+ {
+ if (in_control_form)
+ {
+ fputs_filtered ("'//", stream);
+ in_control_form = 0;
+ }
+ fputs_filtered ("'", stream);
+ in_literal_form = 1;
+ }
+ fprintf_filtered (stream, "%c", c);
+ }
+ else
+ {
+ if (!in_control_form)
+ {
+ if (in_literal_form)
+ {
+ fputs_filtered ("'//", stream);
+ in_literal_form = 0;
+ }
+ fputs_filtered ("c'", stream);
+ in_control_form = 1;
+ }
+ fprintf_filtered (stream, "%.2x", c);
+ }
+ ++things_printed;
+ }
+ }
+
+ /* Terminate the quotes if necessary. */
+ if (in_literal_form || in_control_form)
+ {
+ fputs_filtered ("'", stream);
+ }
+ if (force_ellipses || (i < length))
+ {
+ fputs_filtered ("...", stream);
+ }
+}
+
+static struct type *
+chill_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type *type = NULL;
+
+ switch (typeid)
+ {
+ default:
+ /* FIXME: For now, if we are asked to produce a type not in this
+ language, create the equivalent of a C integer type with the
+ name "<?type?>". When all the dust settles from the type
+ reconstruction work, this should probably become an error. */
+ type = init_type (TYPE_CODE_INT, 2, 0, "<?type?>", objfile);
+ warning ("internal error: no chill fundamental type %d", typeid);
+ break;
+ case FT_VOID:
+ /* FIXME: Currently the GNU Chill compiler emits some DWARF entries for
+ typedefs, unrelated to anything directly in the code being compiled,
+ that have some FT_VOID types. Just fake it for now. */
+ type = init_type (TYPE_CODE_VOID, 0, 0, "<?VOID?>", objfile);
+ break;
+ case FT_BOOLEAN:
+ type = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED, "BOOL", objfile);
+ break;
+ case FT_CHAR:
+ type = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED, "CHAR", objfile);
+ break;
+ case FT_SIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_SIGNED, "BYTE", objfile);
+ break;
+ case FT_UNSIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED, "UBYTE", objfile);
+ break;
+ case FT_SHORT: /* Chill ints are 2 bytes */
+ type = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_SIGNED, "INT", objfile);
+ break;
+ case FT_UNSIGNED_SHORT: /* Chill ints are 2 bytes */
+ type = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED, "UINT", objfile);
+ break;
+ case FT_INTEGER: /* FIXME? */
+ case FT_SIGNED_INTEGER: /* FIXME? */
+ case FT_LONG: /* Chill longs are 4 bytes */
+ case FT_SIGNED_LONG: /* Chill longs are 4 bytes */
+ type = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_SIGNED, "LONG", objfile);
+ break;
+ case FT_UNSIGNED_INTEGER: /* FIXME? */
+ case FT_UNSIGNED_LONG: /* Chill longs are 4 bytes */
+ type = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED, "ULONG", objfile);
+ break;
+ case FT_FLOAT:
+ type = init_type (TYPE_CODE_FLT, 4, 0, "REAL", objfile);
+ break;
+ case FT_DBL_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT, 8, 0, "LONG_REAL", objfile);
+ break;
+ }
+ return (type);
+}
+
+
+/* Table of operators and their precedences for printing expressions. */
+
+static const struct op_print chill_op_print_tab[] = {
+ {"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+ {"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+ {"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+ {"MOD", BINOP_MOD, PREC_MUL, 0},
+ {"REM", BINOP_REM, PREC_MUL, 0},
+ {":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"=", 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_ADD, PREC_ADD, 0},
+ {"-", BINOP_SUB, PREC_ADD, 0},
+ {"*", BINOP_MUL, PREC_MUL, 0},
+ {"/", BINOP_DIV, PREC_MUL, 0},
+ {"//", BINOP_CONCAT, PREC_PREFIX, 0}, /* FIXME: precedence? */
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {NULL, 0, 0, 0}
+};
+
+
+/* The built-in types of Chill. */
+
+struct type *builtin_type_chill_bool;
+struct type *builtin_type_chill_char;
+struct type *builtin_type_chill_long;
+struct type *builtin_type_chill_ulong;
+struct type *builtin_type_chill_real;
+
+struct type ** const (chill_builtin_types[]) =
+{
+ &builtin_type_chill_bool,
+ &builtin_type_chill_char,
+ &builtin_type_chill_long,
+ &builtin_type_chill_ulong,
+ &builtin_type_chill_real,
+ 0
+};
+
+const struct language_defn chill_language_defn = {
+ "chill",
+ language_chill,
+ chill_builtin_types,
+ range_check_on,
+ type_check_on,
+ chill_parse, /* parser */
+ chill_error, /* parser error function */
+ chill_printchar, /* print a character constant */
+ chill_printstr, /* function to print a string constant */
+ chill_create_fundamental_type,/* Create fundamental type in this language */
+ chill_print_type, /* Print a type using appropriate syntax */
+ chill_val_print, /* Print a value using appropriate syntax */
+ &BUILTIN_TYPE_LONGEST, /* longest signed integral type */
+ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */
+ &builtin_type_chill_real, /* longest floating point type */
+ {"", "B'", "", ""}, /* Binary format info */
+ {"O'%lo", "O'", "o", ""}, /* Octal format info */
+ {"D'%ld", "D'", "d", ""}, /* Decimal format info */
+ {"H'%lx", "H'", "x", ""}, /* Hex format info */
+ chill_op_print_tab, /* expression operators for printing */
+ LANG_MAGIC
+};
+
+/* Initialization for Chill */
+
+void
+_initialize_chill_language ()
+{
+ builtin_type_chill_bool =
+ init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "BOOL", (struct objfile *) NULL);
+ builtin_type_chill_char =
+ init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "CHAR", (struct objfile *) NULL);
+ builtin_type_chill_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0,
+ "LONG", (struct objfile *) NULL);
+ builtin_type_chill_ulong =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "ULONG", (struct objfile *) NULL);
+ builtin_type_chill_real =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "LONG_REAL", (struct objfile *) NULL);
+
+ add_language (&chill_language_defn);
+}
diff --git a/gnu/usr.bin/gdb/gdb/ch-lang.h b/gnu/usr.bin/gdb/gdb/ch-lang.h
new file mode 100644
index 000000000000..13579d9d47cb
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/ch-lang.h
@@ -0,0 +1,31 @@
+/* Chill language support definitions for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern int
+chill_parse PARAMS ((void)); /* Defined in ch-exp.y */
+
+extern void
+chill_error PARAMS ((char *)); /* Defined in ch-exp.y */
+
+extern void /* Defined in ch-typeprint.c */
+chill_print_type PARAMS ((struct type *, char *, FILE *, int, int));
+
+extern int
+chill_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int,
+ int, enum val_prettyprint));
diff --git a/gnu/usr.bin/gdb/gdb/ch-typeprint.c b/gnu/usr.bin/gdb/gdb/ch-typeprint.c
new file mode 100644
index 000000000000..c3cdcd2a1885
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/ch-typeprint.c
@@ -0,0 +1,225 @@
+/* Support for printing Chill types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "demangle.h"
+#include "ch-lang.h"
+
+#include <string.h>
+#include <errno.h>
+
+static void
+chill_type_print_base PARAMS ((struct type *, FILE *, int, int));
+
+void
+chill_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ FILE *stream;
+ int show;
+ int level;
+{
+ if (varstring != NULL && *varstring != '\0')
+ {
+ fputs_filtered (varstring, stream);
+ fputs_filtered (" ", stream);
+ }
+ chill_type_print_base (type, stream, show, level);
+}
+
+/* Print the name of the type (or the ultimate pointer target,
+ function value or array element).
+
+ 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 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
+chill_type_print_base (type, stream, show, level)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int level;
+{
+ char *name;
+ register int len;
+ register int i;
+ struct type *index_type;
+ struct type *range_type;
+ LONGEST low_bound;
+ LONGEST high_bound;
+
+ QUIT;
+
+ wrap_here (" ");
+ if (type == NULL)
+ {
+ fputs_filtered ("<type unknown>", stream);
+ return;
+ }
+
+ /* When SHOW is zero or less, and there is a valid type name, then always
+ just print the type name directly from the type. */
+
+ if ((show <= 0) && (TYPE_NAME (type) != NULL))
+ {
+ fputs_filtered (TYPE_NAME (type), stream);
+ return;
+ }
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream, "PTR");
+ break;
+ }
+ fprintf_filtered (stream, "REF ");
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+
+ case TYPE_CODE_ARRAY:
+ range_type = TYPE_FIELD_TYPE (type, 0);
+ index_type = TYPE_TARGET_TYPE (range_type);
+ low_bound = TYPE_FIELD_BITPOS (range_type, 0);
+ high_bound = TYPE_FIELD_BITPOS (range_type, 1);
+ fputs_filtered ("ARRAY (", stream);
+ print_type_scalar (index_type, low_bound, stream);
+ fputs_filtered (":", stream);
+ print_type_scalar (index_type, high_bound, stream);
+ fputs_filtered (") ", stream);
+ chill_print_type (TYPE_TARGET_TYPE (type), "", stream, show, level);
+ break;
+
+ case TYPE_CODE_STRING:
+ range_type = TYPE_FIELD_TYPE (type, 0);
+ index_type = TYPE_TARGET_TYPE (range_type);
+ high_bound = TYPE_FIELD_BITPOS (range_type, 1);
+ fputs_filtered ("CHAR (", stream);
+ print_type_scalar (index_type, high_bound + 1, stream);
+ fputs_filtered (")", stream);
+ break;
+
+ case TYPE_CODE_MEMBER:
+ fprintf_filtered (stream, "MEMBER ");
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+ case TYPE_CODE_REF:
+ fprintf_filtered (stream, "/*LOC*/ ");
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+ case TYPE_CODE_FUNC:
+ fprintf_filtered (stream, "PROC (?)");
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+
+ case TYPE_CODE_STRUCT:
+ fprintf_filtered (stream, "STRUCT ");
+ if ((name = type_name_no_tag (type)) != NULL)
+ {
+ fputs_filtered (name, stream);
+ fputs_filtered (" ", stream);
+ wrap_here (" ");
+ }
+ if (show < 0)
+ {
+ fprintf_filtered (stream, "(...)");
+ }
+ else
+ {
+ check_stub_type (type);
+ fprintf_filtered (stream, "(\n");
+ if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
+ {
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ {
+ fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
+ }
+ else
+ {
+ fprintfi_filtered (level + 4, stream, "<no data fields>\n");
+ }
+ }
+ else
+ {
+ len = TYPE_NFIELDS (type);
+ for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+ {
+ QUIT;
+ print_spaces_filtered (level + 4, stream);
+ chill_print_type (TYPE_FIELD_TYPE (type, i),
+ TYPE_FIELD_NAME (type, i),
+ stream, show - 1, level + 4);
+ if (i < (len - 1))
+ {
+ fputs_filtered (",", stream);
+ }
+ fputs_filtered ("\n", stream);
+ }
+ }
+ fprintfi_filtered (level, stream, ")");
+ }
+ break;
+
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_METHOD:
+ error ("missing language support in chill_type_print_base");
+ break;
+
+ default:
+
+ /* Handle types not explicitly handled by the other cases,
+ such as fundamental types. For these, just print whatever
+ the type name is, as recorded in the type itself. If there
+ is no type name, then complain. */
+
+ if (TYPE_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_NAME (type), stream);
+ }
+ else
+ {
+ error ("Unrecognized type code (%d) in symbol table.",
+ TYPE_CODE (type));
+ }
+ break;
+ }
+}
diff --git a/gnu/usr.bin/gdb/gdb/ch-valprint.c b/gnu/usr.bin/gdb/gdb/ch-valprint.c
new file mode 100644
index 000000000000..261b22ee62c6
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/ch-valprint.c
@@ -0,0 +1,332 @@
+/* Support for printing Chill values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "valprint.h"
+#include "expression.h"
+#include "value.h"
+#include "language.h"
+#include "demangle.h"
+
+static void
+chill_print_value_fields PARAMS ((struct type *, char *, FILE *, int, int,
+ enum val_prettyprint, struct type **));
+
+
+/* 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 string characters
+ printed.
+
+ If DEREF_REF is nonzero, then dereference references, otherwise just print
+ them like pointers.
+
+ The PRETTY parameter controls prettyprinting. */
+
+int
+chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ LONGEST val;
+ unsigned int i = 0; /* Number of characters printed. */
+ struct type *elttype;
+ CORE_ADDR addr;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ {
+ if (prettyprint_arrays)
+ {
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ fprintf_filtered (stream, "[");
+ val_print_array_elements (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty, 0);
+ fprintf_filtered (stream, "]");
+ }
+ else
+ {
+ error ("unimplemented in chill_val_print; unspecified array length");
+ }
+ break;
+
+ case TYPE_CODE_INT:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ val_print_type_code_int (type, valaddr, stream);
+ }
+ break;
+
+ case TYPE_CODE_CHAR:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr),
+ 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_BOOL:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ val = unpack_long (builtin_type_chill_bool, valaddr);
+ fprintf_filtered (stream, val ? "TRUE" : "FALSE");
+ }
+ 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, "<incomplete type>");
+ break;
+
+ case TYPE_CODE_PTR:
+ if (format && format != 's')
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ addr = unpack_pointer (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, "H'%lx", (unsigned long) addr);
+ }
+
+ /* For a pointer to char or unsigned char, also print the string
+ pointed to, unless pointer is null. */
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_CHAR
+ && (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)
+ {
+ i = val_print_string (addr, 0, 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_STRING:
+ if (format && format != 's')
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ if (addressprint && format != 's')
+ {
+ /* This used to say `addr', which is unset at this point.
+ Is `address' what is meant? */
+ fprintf_filtered (stream, "H'%lx ", (unsigned long) address);
+ }
+ i = TYPE_LENGTH (type);
+ LA_PRINT_STRING (stream, valaddr, i, 0);
+ /* 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_STRUCT:
+ chill_print_value_fields (type, valaddr, stream, format, recurse, pretty,
+ 0);
+ break;
+
+ case TYPE_CODE_REF:
+ if (addressprint)
+ {
+ fprintf_filtered (stream, "LOC(H'%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 deref_val =
+ value_at
+ (TYPE_TARGET_TYPE (type),
+ unpack_pointer (lookup_pointer_type (builtin_type_void),
+ valaddr));
+ val_print (VALUE_TYPE (deref_val),
+ VALUE_CONTENTS (deref_val),
+ VALUE_ADDRESS (deref_val), stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ else
+ fputs_filtered ("???", stream);
+ }
+ break;
+
+ case TYPE_CODE_ENUM:
+ c_val_print (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+ break;
+
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_RANGE:
+ default:
+ /* Let's derfer printing to the C printer, rather than
+ print an error message. FIXME! */
+ c_val_print (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+ }
+ fflush (stream);
+ return (0);
+}
+
+/* Mutually recursive subroutines of cplus_print_value and c_val_print to
+ print out a structure's fields: cp_print_value_fields and cplus_print_value.
+
+ TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the
+ same meanings as in cplus_print_value and c_val_print.
+
+ DONT_PRINT is an array of baseclass types that we
+ should not print, or zero if called from top level. */
+
+static void
+chill_print_value_fields (type, valaddr, stream, format, recurse, pretty,
+ dont_print)
+ struct type *type;
+ char *valaddr;
+ FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+ struct type **dont_print;
+{
+ int i, len;
+ int fields_seen = 0;
+
+ check_stub_type (type);
+
+ fprintf_filtered (stream, "[");
+ len = TYPE_NFIELDS (type);
+ if (len == 0)
+ {
+ fprintf_filtered (stream, "<No data fields>");
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ {
+ if (fields_seen)
+ {
+ fprintf_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));
+ }
+ fputs_filtered (".", stream);
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_chill, DMGL_NO_OPTS);
+ fputs_filtered (": ", stream);
+ if (TYPE_FIELD_PACKED (type, i))
+ {
+ value v;
+
+ /* Bitfields require special handling, especially due to byte
+ order problems. */
+ v = value_from_longest (TYPE_FIELD_TYPE (type, i),
+ unpack_field_as_long (type, valaddr, i));
+
+ chill_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0,
+ stream, format, 0, recurse + 1, pretty);
+ }
+ else
+ {
+ chill_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, "]");
+}
+
diff --git a/gnu/usr.bin/gdb/gdb/coff/ecoff.h b/gnu/usr.bin/gdb/gdb/coff/ecoff.h
new file mode 100644
index 000000000000..8c7cee243ea9
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/coff/ecoff.h
@@ -0,0 +1,262 @@
+#ifndef ECOFF_H
+#define ECOFF_H
+
+/* Generic ECOFF support.
+ This does not include symbol information, found in sym.h and
+ symconst.h. */
+
+/* Mips magic numbers used in filehdr. MIPS_MAGIC_LITTLE is used on
+ little endian machines. MIPS_MAGIC_BIG is used on big endian
+ machines. Where is MIPS_MAGIC_1 from? */
+#define MIPS_MAGIC_1 0x0180
+#define MIPS_MAGIC_LITTLE 0x0162
+#define MIPS_MAGIC_BIG 0x0160
+
+/* These are the magic numbers used for MIPS code compiled at ISA
+ level 2. */
+#define MIPS_MAGIC_LITTLE2 0x0166
+#define MIPS_MAGIC_BIG2 0x0163
+
+/* These are the magic numbers used for MIPS code compiled at ISA
+ level 3. */
+#define MIPS_MAGIC_LITTLE3 0x142
+#define MIPS_MAGIC_BIG3 0x140
+
+/* Alpha magic numbers used in filehdr. */
+#define ALPHA_MAGIC 0x183
+
+/* Magic numbers used in a.out header. */
+#define ECOFF_AOUT_OMAGIC 0407 /* not demand paged (ld -N). */
+#define ECOFF_AOUT_ZMAGIC 0413 /* demand load format, eg normal ld output */
+
+/* Names of special sections. */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _RDATA ".rdata"
+#define _SDATA ".sdata"
+#define _SBSS ".sbss"
+#define _LIT4 ".lit4"
+#define _LIT8 ".lit8"
+#define _LIB ".lib"
+#define _INIT ".init"
+#define _FINI ".fini"
+
+/* ECOFF uses some additional section flags. */
+#define STYP_RDATA 0x100
+#define STYP_SDATA 0x200
+#define STYP_SBSS 0x400
+#define STYP_ECOFF_FINI 0x1000000
+#define STYP_LIT8 0x8000000
+#define STYP_LIT4 0x10000000
+#define STYP_ECOFF_INIT 0x80000000
+#define STYP_OTHER_LOAD (STYP_ECOFF_INIT | STYP_ECOFF_FINI)
+
+/* The linker needs a section to hold small common variables while
+ linking. There is no convenient way to create it when the linker
+ needs it, so we always create one for each BFD. We then avoid
+ writing it out. */
+#define SCOMMON ".scommon"
+
+/* The ECOFF a.out header carries information about register masks and
+ the gp value. The assembler needs to be able to write out this
+ information, and objcopy needs to be able to copy it from one file
+ to another. To handle this in BFD, we use a dummy section to hold
+ the information. We call this section .reginfo, since MIPS ELF has
+ a .reginfo section which serves a similar purpose. When BFD
+ recognizes an ECOFF object, it copies the information into a
+ private data structure. When the .reginfo section is read, the
+ information is retrieved from the private data structure. When the
+ .reginfo section is written, the information in the private data
+ structure is updated. The contents of the .reginfo section, as
+ seen by programs outside BFD, is a ecoff_reginfo structure. The
+ contents of the structure are as seen on the host, so no swapping
+ issues arise.
+
+ The assembler used to update the private BFD data structures
+ directly. With this approach, it instead just creates a .reginfo
+ section and updates that. The real advantage of this approach is
+ that objcopy works automatically. */
+#define REGINFO ".reginfo"
+struct ecoff_reginfo
+{
+ bfd_vma gp_value; /* GP register value. */
+ unsigned long gprmask; /* General registers used. */
+ unsigned long cprmask[4]; /* Coprocessor registers used. */
+ unsigned long fprmask; /* Floating pointer registers used. */
+};
+
+/* If the extern bit in a reloc is 1, then r_symndx is an index into
+ the external symbol table. If the extern bit is 0, then r_symndx
+ indicates a section, and is one of the following values. */
+#define RELOC_SECTION_NONE 0
+#define RELOC_SECTION_TEXT 1
+#define RELOC_SECTION_RDATA 2
+#define RELOC_SECTION_DATA 3
+#define RELOC_SECTION_SDATA 4
+#define RELOC_SECTION_SBSS 5
+#define RELOC_SECTION_BSS 6
+#define RELOC_SECTION_INIT 7
+#define RELOC_SECTION_LIT8 8
+#define RELOC_SECTION_LIT4 9
+#define RELOC_SECTION_XDATA 10
+#define RELOC_SECTION_PDATA 11
+#define RELOC_SECTION_FINI 12
+#define RELOC_SECTION_LITA 13
+#define RELOC_SECTION_ABS 14
+
+/********************** STABS **********************/
+
+/* gcc uses mips-tfile to output type information in special stabs
+ entries. These must match the corresponding definition in
+ gcc/config/mips.h. At some point, these should probably go into a
+ shared include file, but currently gcc and gdb do not share any
+ directories. */
+#define CODE_MASK 0x8F300
+#define ECOFF_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
+#define ECOFF_MARK_STAB(code) ((code)+CODE_MASK)
+#define ECOFF_UNMARK_STAB(code) ((code)-CODE_MASK)
+#define STABS_SYMBOL "@stabs"
+
+/********************** COFF **********************/
+
+/* gcc also uses mips-tfile to output COFF debugging information.
+ These are the values it uses when outputting the .type directive.
+ These should also be in a shared include file. */
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+/********************** AUX **********************/
+
+/* The auxiliary type information is the same on all known ECOFF
+ targets. I can't see any reason that it would ever change, so I am
+ going to gamble and define the external structures here, in the
+ target independent ECOFF header file. The internal forms are
+ defined in coff/sym.h, which was originally donated by MIPS
+ Computer Systems. */
+
+/* Type information external record */
+
+struct tir_ext {
+ unsigned char t_bits1[1];
+ unsigned char t_tq45[1];
+ unsigned char t_tq01[1];
+ unsigned char t_tq23[1];
+};
+
+#define TIR_BITS1_FBITFIELD_BIG 0x80
+#define TIR_BITS1_FBITFIELD_LITTLE 0x01
+
+#define TIR_BITS1_CONTINUED_BIG 0x40
+#define TIR_BITS1_CONTINUED_LITTLE 0x02
+
+#define TIR_BITS1_BT_BIG 0x3F
+#define TIR_BITS1_BT_SH_BIG 0
+#define TIR_BITS1_BT_LITTLE 0xFC
+#define TIR_BITS1_BT_SH_LITTLE 2
+
+#define TIR_BITS_TQ4_BIG 0xF0
+#define TIR_BITS_TQ4_SH_BIG 4
+#define TIR_BITS_TQ5_BIG 0x0F
+#define TIR_BITS_TQ5_SH_BIG 0
+#define TIR_BITS_TQ4_LITTLE 0x0F
+#define TIR_BITS_TQ4_SH_LITTLE 0
+#define TIR_BITS_TQ5_LITTLE 0xF0
+#define TIR_BITS_TQ5_SH_LITTLE 4
+
+#define TIR_BITS_TQ0_BIG 0xF0
+#define TIR_BITS_TQ0_SH_BIG 4
+#define TIR_BITS_TQ1_BIG 0x0F
+#define TIR_BITS_TQ1_SH_BIG 0
+#define TIR_BITS_TQ0_LITTLE 0x0F
+#define TIR_BITS_TQ0_SH_LITTLE 0
+#define TIR_BITS_TQ1_LITTLE 0xF0
+#define TIR_BITS_TQ1_SH_LITTLE 4
+
+#define TIR_BITS_TQ2_BIG 0xF0
+#define TIR_BITS_TQ2_SH_BIG 4
+#define TIR_BITS_TQ3_BIG 0x0F
+#define TIR_BITS_TQ3_SH_BIG 0
+#define TIR_BITS_TQ2_LITTLE 0x0F
+#define TIR_BITS_TQ2_SH_LITTLE 0
+#define TIR_BITS_TQ3_LITTLE 0xF0
+#define TIR_BITS_TQ3_SH_LITTLE 4
+
+/* Relative symbol external record */
+
+struct rndx_ext {
+ unsigned char r_bits[4];
+};
+
+#define RNDX_BITS0_RFD_SH_LEFT_BIG 4
+#define RNDX_BITS1_RFD_BIG 0xF0
+#define RNDX_BITS1_RFD_SH_BIG 4
+
+#define RNDX_BITS0_RFD_SH_LEFT_LITTLE 0
+#define RNDX_BITS1_RFD_LITTLE 0x0F
+#define RNDX_BITS1_RFD_SH_LEFT_LITTLE 8
+
+#define RNDX_BITS1_INDEX_BIG 0x0F
+#define RNDX_BITS1_INDEX_SH_LEFT_BIG 16
+#define RNDX_BITS2_INDEX_SH_LEFT_BIG 8
+#define RNDX_BITS3_INDEX_SH_LEFT_BIG 0
+
+#define RNDX_BITS1_INDEX_LITTLE 0xF0
+#define RNDX_BITS1_INDEX_SH_LITTLE 4
+#define RNDX_BITS2_INDEX_SH_LEFT_LITTLE 4
+#define RNDX_BITS3_INDEX_SH_LEFT_LITTLE 12
+
+/* Auxiliary symbol information external record */
+
+union aux_ext {
+ struct tir_ext a_ti;
+ struct rndx_ext a_rndx;
+ unsigned char a_dnLow[4];
+ unsigned char a_dnHigh[4];
+ unsigned char a_isym[4];
+ unsigned char a_iss[4];
+ unsigned char a_width[4];
+ unsigned char a_count[4];
+};
+
+#define AUX_GET_ANY(bigend, ax, field) \
+ ((bigend) ? bfd_getb32 ((ax)->field) : bfd_getl32 ((ax)->field))
+
+#define AUX_GET_DNLOW(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_dnLow)
+#define AUX_GET_DNHIGH(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_dnHigh)
+#define AUX_GET_ISYM(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_isym)
+#define AUX_GET_ISS(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_iss)
+#define AUX_GET_WIDTH(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_width)
+#define AUX_GET_COUNT(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_count)
+
+#define AUX_PUT_ANY(bigend, val, ax, field) \
+ ((bigend) \
+ ? (bfd_putb32 ((bfd_vma) (val), (ax)->field), 0) \
+ : (bfd_putl32 ((bfd_vma) (val), (ax)->field), 0))
+
+#define AUX_PUT_DNLOW(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_dnLow)
+#define AUX_PUT_DNHIGH(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_dnHigh)
+#define AUX_PUT_ISYM(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_isym)
+#define AUX_PUT_ISS(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_iss)
+#define AUX_PUT_WIDTH(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_width)
+#define AUX_PUT_COUNT(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_count)
+
+/* Prototypes for the swapping functions. These require that sym.h be
+ included before this file. */
+
+extern void ecoff_swap_tir_in PARAMS ((int bigend, struct tir_ext *, TIR *));
+extern void ecoff_swap_tir_out PARAMS ((int bigend, TIR *, struct tir_ext *));
+extern void ecoff_swap_rndx_in PARAMS ((int bigend, struct rndx_ext *,
+ RNDXR *));
+extern void ecoff_swap_rndx_out PARAMS ((int bigend, RNDXR *,
+ struct rndx_ext *));
+
+#endif /* ! defined (ECOFF_H) */
diff --git a/gnu/usr.bin/gdb/gdb/coff/internal.h b/gnu/usr.bin/gdb/gdb/coff/internal.h
new file mode 100644
index 000000000000..e8cf98470cfb
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/coff/internal.h
@@ -0,0 +1,538 @@
+/* Internal format of COFF object file data structures, for GNU BFD.
+ This file is part of BFD, the Binary File Descriptor library. */
+
+/* First, make "signed char" work, even on old compilers. */
+#ifndef signed
+#ifndef __STDC__
+#define signed /**/
+#endif
+#endif
+
+/********************** FILE HEADER **********************/
+struct internal_filehdr
+{
+ unsigned short f_magic; /* magic number */
+ unsigned short f_nscns; /* number of sections */
+ long f_timdat; /* time & date stamp */
+ bfd_vma 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 external references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR16WR file is 16-bit little-endian
+ * F_AR32WR file is 32-bit little-endian
+ * F_AR32W file is 32-bit big-endian
+ * F_DYNLOAD rs/6000 aix: dynamically loadable w/imports & exports
+ * F_SHROBJ rs/6000 aix: file is a shared object
+ */
+
+#define F_RELFLG (0x0001)
+#define F_EXEC (0x0002)
+#define F_LNNO (0x0004)
+#define F_LSYMS (0x0008)
+#define F_AR16WR (0x0080)
+#define F_AR32WR (0x0100)
+#define F_AR32W (0x0200)
+#define F_DYNLOAD (0x1000)
+#define F_SHROBJ (0x2000)
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+struct internal_aouthdr
+{
+ short magic; /* type of file */
+ short vstamp; /* version stamp */
+ bfd_vma tsize; /* text size in bytes, padded to FW bdry*/
+ bfd_vma dsize; /* initialized data " " */
+ bfd_vma bsize; /* uninitialized data " " */
+ bfd_vma entry; /* entry pt. */
+ bfd_vma text_start; /* base of text used for this file */
+ bfd_vma data_start; /* base of data used for this file */
+
+ /* i960 stuff */
+ unsigned long tagentries; /* number of tag entries to follow */
+
+ /* RS/6000 stuff */
+ unsigned long o_toc; /* address of TOC */
+ short o_snentry; /* section number for entry point */
+ short o_sntext; /* section number for text */
+ short o_sndata; /* section number for data */
+ short o_sntoc; /* section number for toc */
+ short o_snloader; /* section number for loader section */
+ short o_snbss; /* section number for bss */
+ short o_algntext; /* max alignment for text */
+ short o_algndata; /* max alignment for data */
+ short o_modtype; /* Module type field, 1R,RE,RO */
+ unsigned long o_maxstack; /* max stack size allowed. */
+
+ /* ECOFF stuff */
+ bfd_vma bss_start; /* Base of bss section. */
+ bfd_vma gp_value; /* GP register value. */
+ unsigned long gprmask; /* General registers used. */
+ unsigned long cprmask[4]; /* Coprocessor registers used. */
+ unsigned long fprmask; /* Floating pointer registers used. */
+
+ /* Apollo stuff */
+ long o_inlib;
+ long o_sri;
+ long vid[2];
+};
+
+/********************** STORAGE CLASSES **********************/
+
+/* This used to be defined as -1, but now n_sclass is unsigned. */
+#define C_EFCN 0xff /* 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 */
+#define C_AUTOARG 19 /* auto argument */
+#define C_LASTENT 20 /* dummy entry (end of block) */
+#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 */
+
+ /* New storage classes for 80960 */
+
+/* C_LEAFPROC is obsolete. Use C_LEAFEXT or C_LEAFSTAT */
+#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */
+
+#define C_SCALL 107 /* Procedure reachable via system call */
+#define C_LEAFEXT 108 /* External leaf */
+#define C_LEAFSTAT 113 /* Static leaf */
+#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 */
+
+ /* Storage classes for m88k */
+#define C_SHADOW 107 /* shadow symbol */
+#define C_VERSION 108 /* coff version symbol */
+
+ /* New storage classes for RS/6000 */
+#define C_HIDEXT 107 /* Un-named external symbol */
+#define C_BINCL 108 /* Marks beginning of include file */
+#define C_EINCL 109 /* Marks ending of include file */
+
+ /* storage classes for stab symbols for RS/6000 */
+#define C_GSYM (0x80)
+#define C_LSYM (0x81)
+#define C_PSYM (0x82)
+#define C_RSYM (0x83)
+#define C_RPSYM (0x84)
+#define C_STSYM (0x85)
+#define C_TCSYM (0x86)
+#define C_BCOMM (0x87)
+#define C_ECOML (0x88)
+#define C_ECOMM (0x89)
+#define C_DECL (0x8c)
+#define C_ENTRY (0x8d)
+#define C_FUN (0x8e)
+#define C_BSTAT (0x8f)
+#define C_ESTAT (0x90)
+
+/********************** SECTION HEADER **********************/
+struct internal_scnhdr
+{
+ char s_name[8]; /* section name */
+ bfd_vma s_paddr; /* physical address, aliased s_nlib */
+ bfd_vma s_vaddr; /* virtual address */
+ bfd_vma s_size; /* section size */
+ bfd_vma s_scnptr; /* file ptr to raw data for section */
+ bfd_vma s_relptr; /* file ptr to relocation */
+ bfd_vma s_lnnoptr; /* file ptr to line numbers */
+ unsigned long s_nreloc; /* number of relocation entries */
+ unsigned long s_nlnno; /* number of line number entries*/
+ long s_flags; /* flags */
+ long s_align; /* used on I960 */
+};
+
+/*
+ * s_flags "type"
+ */
+#define STYP_REG (0x0000) /* "regular": allocated, relocated, loaded */
+#define STYP_DSECT (0x0001) /* "dummy": relocated only*/
+#define STYP_NOLOAD (0x0002) /* "noload": allocated, relocated, not loaded */
+#define STYP_GROUP (0x0004) /* "grouped": formed of input sections */
+#define STYP_PAD (0x0008) /* "padding": not allocated, not relocated, loaded */
+#define STYP_COPY (0x0010) /* "copy": 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: not allocated not relocated, not loaded */
+#define STYP_OVER (0x0400) /* overlay: relocated not allocated or loaded */
+#define STYP_LIB (0x0800) /* for .lib: 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. */
+
+#define STYP_LIT 0x8020 /* Literal data (like STYP_TEXT) */
+/********************** 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 internal_lineno
+{
+ union
+ {
+ long l_symndx; /* function name symbol index, iff l_lnno == 0*/
+ long l_paddr; /* (physical) address of line number */
+ } l_addr;
+ unsigned long l_lnno; /* line number */
+};
+
+/********************** 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 internal_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 */
+ unsigned short n_flags; /* copy of flags from filhdr */
+ unsigned short n_type; /* type and derived type */
+ unsigned char n_sclass; /* storage class */
+ char n_numaux; /* number of aux. entries */
+};
+
+#define n_name _n._n_name
+#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_UNDEF ((short)0) /* undefined symbol */
+#define N_ABS ((short)-1) /* value of symbol is absolute */
+#define N_DEBUG ((short)-2) /* debugging symbol -- value is meaningless */
+#define N_TV ((short)-3) /* indicates symbol needs preload transfer vector */
+#define P_TV ((short)-4) /* indicates symbol needs postload transfer vector*/
+
+/*
+ * Type of a symbol, in low N bits of the word
+ */
+#define T_NULL 0
+#define T_VOID 1 /* function argument (only used by compiler) */
+#define T_CHAR 2 /* character */
+#define T_SHORT 3 /* short integer */
+#define T_INT 4 /* integer */
+#define T_LONG 5 /* long integer */
+#define T_FLOAT 6 /* floating point */
+#define T_DOUBLE 7 /* double word */
+#define T_STRUCT 8 /* structure */
+#define T_UNION 9 /* union */
+#define T_ENUM 10 /* enumeration */
+#define T_MOE 11 /* member of enumeration*/
+#define T_UCHAR 12 /* unsigned character */
+#define T_USHORT 13 /* unsigned short */
+#define T_UINT 14 /* unsigned integer */
+#define T_ULONG 15 /* unsigned long */
+#define T_LNGDBL 16 /* long double */
+
+/*
+ * 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 */
+
+#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 ISTAG(x) ((x)==C_STRTAG||(x)==C_UNTAG||(x)==C_ENTAG)
+#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
+
+
+union internal_auxent
+{
+ struct
+ {
+
+ union
+ {
+ long l; /* str, un, or enum tag indx */
+ struct coff_ptr_struct *p;
+ } x_tagndx;
+
+ 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 # */
+ union
+ { /* entry ndx past block end */
+ long l;
+ struct coff_ptr_struct *p;
+ } x_endndx;
+ } 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;
+
+ 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 */
+ unsigned short x_tvran[2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+ /******************************************
+ * RS/6000-specific auxent - last auxent for every external symbol
+ ******************************************/
+ struct
+ {
+ long x_scnlen; /* csect length */
+ long x_parmhash; /* parm type hash index */
+ unsigned short x_snhash; /* sect num with parm hash */
+ unsigned char x_smtyp; /* symbol align and type */
+ /* 0-4 - Log 2 of alignment */
+ /* 5-7 - symbol type */
+ unsigned char x_smclas; /* storage mapping class */
+ long x_stab; /* dbx stab info index */
+ unsigned short x_snstab; /* sect num with dbx stab */
+ } x_csect; /* csect definition information */
+
+/* x_smtyp values: */
+
+#define SMTYP_ALIGN(x) ((x) >> 3) /* log2 of alignment */
+#define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */
+/* Symbol type values: */
+#define XTY_ER 0 /* External reference */
+#define XTY_SD 1 /* Csect definition */
+#define XTY_LD 2 /* Label definition */
+#define XTY_CM 3 /* .BSS */
+#define XTY_EM 4 /* Error message */
+#define XTY_US 5 /* "Reserved for internal use" */
+
+/* x_smclas values: */
+
+#define XMC_PR 0 /* Read-only program code */
+#define XMC_RO 1 /* Read-only constant */
+#define XMC_DB 2 /* Read-only debug dictionary table */
+#define XMC_TC 3 /* Read-write general TOC entry */
+#define XMC_UA 4 /* Read-write unclassified */
+#define XMC_RW 5 /* Read-write data */
+#define XMC_GL 6 /* Read-only global linkage */
+#define XMC_XO 7 /* Read-only extended operation (simulated insn) */
+#define XMC_SV 8 /* Read-only supervisor call */
+#define XMC_BS 9 /* Read-write BSS */
+#define XMC_DS 10 /* Read-write descriptor csect */
+#define XMC_UC 11 /* Read-write unnamed Fortran common */
+#define XMC_TI 12 /* Read-only traceback index csect */
+#define XMC_TB 13 /* Read-only traceback table csect */
+/* 14 ??? */
+#define XMC_TC0 15 /* Read-write TOC anchor for TOC addressability */
+
+
+ /******************************************
+ * I960-specific *2nd* aux. entry formats
+ ******************************************/
+ struct
+ {
+ /* This is a very old typo that keeps getting propagated. */
+#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 */
+
+};
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct internal_reloc
+{
+ bfd_vma r_vaddr; /* Virtual address of reference */
+ long r_symndx; /* Index into symbol table */
+ unsigned short r_type; /* Relocation type */
+ unsigned char r_size; /* Used by RS/6000 and ECOFF */
+ unsigned char r_extern; /* Used by ECOFF */
+ unsigned long r_offset; /* Used by RS/6000 and ECOFF */
+};
+
+#define R_RELBYTE 017
+#define R_RELWORD 020
+#define R_PCRBYTE 022
+#define R_PCRWORD 023
+#define R_PCRLONG 024
+
+#define R_DIR16 01
+#define R_DIR32 06
+#define R_PCLONG 020
+#define R_RELBYTE 017
+#define R_RELWORD 020
+
+
+
+#define R_PCR16L 128
+#define R_PCR26L 129
+#define R_VRT16 130
+#define R_HVRT16 131
+#define R_LVRT16 132
+#define R_VRT32 133
+#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)
+#define R_JUMPTARG 0x20 /* strange 29k 00xx00xx reloc */
+
+
+#define R_MOVB1 0x41 /* Special h8 16bit or 8 bit reloc for mov.b */
+#define R_MOVB2 0x42 /* Special h8 opcode for 8bit which could be 16 */
+#define R_JMP1 0x43 /* Special h8 16bit jmp which could be pcrel */
+#define R_JMP2 0x44 /* a branch which used to be a jmp */
+#define R_RELLONG_NEG 0x45
+
+#define R_JMPL1 0x46 /* Special h8 24bit jmp which could be pcrel */
+#define R_JMPL_B8 0x47 /* a 8 bit pcrel which used to be a jmp */
+
+#define R_MOVLB1 0x48 /* Special h8 24bit or 8 bit reloc for mov.b */
+#define R_MOVLB2 0x49 /* Special h8 opcode for 8bit which could be 24 */
+
+/* Z8k modes */
+#define R_IMM16 0x01 /* 16 bit abs */
+#define R_JR 0x02 /* jr 8 bit disp */
+#define R_IMM4L 0x23 /* low nibble */
+#define R_IMM8 0x22 /* 8 bit abs */
+#define R_IMM32 R_RELLONG /* 32 bit abs */
+#define R_CALL R_DA /* Absolute address which could be a callr */
+#define R_JP R_DA /* Absolute address which could be a jp */
+#define R_REL16 0x04 /* 16 bit PC rel */
+#define R_CALLR 0x05 /* callr 12 bit disp */
+#define R_SEG 0x10 /* set if in segmented mode */
+#define R_IMM4H 0x24 /* high nibble */
+
+
+/* H8500 modes */
+
+#define R_H8500_IMM8 1 /* 8 bit immediate */
+#define R_H8500_IMM16 2 /* 16 bit immediate */
+#define R_H8500_PCREL8 3 /* 8 bit pcrel */
+#define R_H8500_PCREL16 4 /* 16 bit pcrel */
+#define R_H8500_HIGH8 5 /* high 8 bits of 24 bit address */
+#define R_H8500_LOW16 7 /* low 16 bits of 24 bit immediate */
+#define R_H8500_IMM24 6 /* 24 bit immediate */
+#define R_H8500_IMM32 8 /* 32 bit immediate */
+#define R_H8500_HIGH16 9 /* high 16 bits of 32 bit immediate */
+
+/* SH modes */
+
+#define R_SH_PCREL8 3 /* 8 bit pcrel */
+#define R_SH_PCREL16 4 /* 16 bit pcrel */
+#define R_SH_HIGH8 5 /* high 8 bits of 24 bit address */
+#define R_SH_LOW16 7 /* low 16 bits of 24 bit immediate */
+#define R_SH_IMM24 6 /* 24 bit immediate */
+#define R_SH_PCDISP8BY4 9 /* PC rel 8 bits *4 +ve */
+#define R_SH_PCDISP8BY2 10 /* PC rel 8 bits *2 +ve */
+#define R_SH_PCDISP8 11 /* 8 bit branch */
+#define R_SH_PCDISP 12 /* 12 bit branch */
+#define R_SH_IMM32 14 /* 32 bit immediate */
+#define R_SH_IMM8 16
+#define R_SH_IMM8BY2 17
+#define R_SH_IMM8BY4 18
+#define R_SH_IMM4 19
+#define R_SH_IMM4BY2 20
+#define R_SH_IMM4BY4 21
+#define R_SH_PCRELIMM8BY2 22
+#define R_SH_PCRELIMM8BY4 23
+
+
+
diff --git a/gnu/usr.bin/gdb/gdb/coff/sym.h b/gnu/usr.bin/gdb/gdb/coff/sym.h
new file mode 100644
index 000000000000..990eeacc6809
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/coff/sym.h
@@ -0,0 +1,477 @@
+/* Declarations of internal format of MIPS ECOFF symbols.
+ Originally contributed by MIPS Computer Systems and Third Eye Software.
+ Changes contributed by Cygnus Support are in the public domain.
+
+ This file is just aggregated with the files that make up the GNU
+ release; it is not considered part of GAS, GDB, or other GNU
+ programs. */
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
+ * | MIPS Computer Systems, Inc. grants reproduction and use |
+ * | rights to all parties, PROVIDED that this comment is |
+ * | maintained in the copy. |
+ * |-----------------------------------------------------------|
+ */
+#ifndef _SYM_H
+#define _SYM_H
+
+/* (C) Copyright 1984 by Third Eye Software, Inc.
+ *
+ * Third Eye Software, Inc. grants reproduction and use rights to
+ * all parties, PROVIDED that this comment is maintained in the copy.
+ *
+ * Third Eye makes no claims about the applicability of this
+ * symbol table to a particular use.
+ */
+
+/*
+ * This file contains the definition of the Third Eye Symbol Table.
+ *
+ * Symbols are assumed to be in 'encounter order' - i.e. the order that
+ * the things they represent were encountered by the compiler/assembler/loader.
+ * EXCEPT for globals! These are assumed to be bunched together,
+ * probably right after the last 'normal' symbol. Globals ARE sorted
+ * in ascending order.
+ *
+ * -----------------------------------------------------------------------
+ * A brief word about Third Eye naming/use conventions:
+ *
+ * All arrays and index's are 0 based.
+ * All "ifooMax" values are the highest legal value PLUS ONE. This makes
+ * them good for allocating arrays, etc. All checks are "ifoo < ifooMax".
+ *
+ * "isym" Index into the SYMbol table.
+ * "ipd" Index into the Procedure Descriptor array.
+ * "ifd" Index into the File Descriptor array.
+ * "iss" Index into String Space.
+ * "cb" Count of Bytes.
+ * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR.
+ * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR.
+ */
+
+
+/*
+ * Symbolic Header (HDR) structure.
+ * As long as all the pointers are set correctly,
+ * we don't care WHAT order the various sections come out in!
+ *
+ * A file produced solely for the use of CDB will probably NOT have
+ * any instructions or data areas in it, as these are available
+ * in the original.
+ */
+
+typedef struct {
+ short magic; /* to verify validity of the table */
+ short vstamp; /* version stamp */
+ long ilineMax; /* number of line number entries */
+ bfd_vma cbLine; /* number of bytes for line number entries */
+ bfd_vma cbLineOffset; /* offset to start of line number entries*/
+ long idnMax; /* max index into dense number table */
+ bfd_vma cbDnOffset; /* offset to start dense number table */
+ long ipdMax; /* number of procedures */
+ bfd_vma cbPdOffset; /* offset to procedure descriptor table */
+ long isymMax; /* number of local symbols */
+ bfd_vma cbSymOffset; /* offset to start of local symbols*/
+ long ioptMax; /* max index into optimization symbol entries */
+ bfd_vma cbOptOffset; /* offset to optimization symbol entries */
+ long iauxMax; /* number of auxillary symbol entries */
+ bfd_vma cbAuxOffset; /* offset to start of auxillary symbol entries*/
+ long issMax; /* max index into local strings */
+ bfd_vma cbSsOffset; /* offset to start of local strings */
+ long issExtMax; /* max index into external strings */
+ bfd_vma cbSsExtOffset; /* offset to start of external strings */
+ long ifdMax; /* number of file descriptor entries */
+ bfd_vma cbFdOffset; /* offset to file descriptor table */
+ long crfd; /* number of relative file descriptor entries */
+ bfd_vma cbRfdOffset; /* offset to relative file descriptor table */
+ long iextMax; /* max index into external symbols */
+ bfd_vma cbExtOffset; /* offset to start of external symbol entries*/
+ /* If you add machine dependent fields, add them here */
+ } HDRR, *pHDRR;
+#define cbHDRR sizeof(HDRR)
+#define hdrNil ((pHDRR)0)
+
+/*
+ * The FDR and PDR structures speed mapping of address <-> name.
+ * They are sorted in ascending memory order and are kept in
+ * memory by CDB at runtime.
+ */
+
+/*
+ * File Descriptor
+ *
+ * There is one of these for EVERY FILE, whether compiled with
+ * full debugging symbols or not. The name of a file should be
+ * the path name given to the compiler. This allows the user
+ * to simply specify the names of the directories where the COMPILES
+ * were done, and we will be able to find their files.
+ * A field whose comment starts with "R - " indicates that it will be
+ * setup at runtime.
+ */
+typedef struct fdr {
+ bfd_vma adr; /* memory address of beginning of file */
+ long rss; /* file name (of source, if known) */
+ long issBase; /* file's string space */
+ bfd_vma cbSs; /* number of bytes in the ss */
+ long isymBase; /* beginning of symbols */
+ long csym; /* count file's of symbols */
+ long ilineBase; /* file's line symbols */
+ long cline; /* count of file's line symbols */
+ long ioptBase; /* file's optimization entries */
+ long copt; /* count of file's optimization entries */
+ unsigned short ipdFirst;/* start of procedures for this file */
+ short cpd; /* count of procedures for this file */
+ long iauxBase; /* file's auxiliary entries */
+ long caux; /* count of file's auxiliary entries */
+ long rfdBase; /* index into the file indirect table */
+ long crfd; /* count file indirect entries */
+ unsigned lang: 5; /* language for this file */
+ unsigned fMerge : 1; /* whether this file can be merged */
+ unsigned fReadin : 1; /* true if it was read in (not just created) */
+ unsigned fBigendian : 1;/* if set, was compiled on big endian machine */
+ /* aux's will be in compile host's sex */
+ unsigned glevel : 2; /* level this file was compiled with */
+ unsigned reserved : 22; /* reserved for future use */
+ bfd_vma cbLineOffset; /* byte offset from header for this file ln's */
+ bfd_vma cbLine; /* size of lines for this file */
+ } FDR, *pFDR;
+#define cbFDR sizeof(FDR)
+#define fdNil ((pFDR)0)
+#define ifdNil -1
+#define ifdTemp 0
+#define ilnNil -1
+
+
+/*
+ * Procedure Descriptor
+ *
+ * There is one of these for EVERY TEXT LABEL.
+ * If a procedure is in a file with full symbols, then isym
+ * will point to the PROC symbols, else it will point to the
+ * global symbol for the label.
+ */
+
+typedef struct pdr {
+ bfd_vma adr; /* memory address of start of procedure */
+ long isym; /* start of local symbol entries */
+ long iline; /* start of line number entries*/
+ long regmask; /* save register mask */
+ long regoffset; /* save register offset */
+ long iopt; /* start of optimization symbol entries*/
+ long fregmask; /* save floating point register mask */
+ long fregoffset; /* save floating point register offset */
+ long 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 */
+ bfd_vma cbLineOffset; /* byte offset for this procedure from the fd base */
+ /* These fields are new for 64 bit ECOFF. */
+ unsigned gp_prologue : 8; /* byte size of GP prologue */
+ unsigned gp_used : 1; /* true if the procedure uses GP */
+ unsigned reg_frame : 1; /* true if register frame procedure */
+ unsigned reserved : 14; /* reserved: must be zero */
+ unsigned localoff : 8; /* offset of local variables from vfp */
+ } PDR, *pPDR;
+#define cbPDR sizeof(PDR)
+#define pdNil ((pPDR) 0)
+#define ipdNil -1
+
+/*
+ * The structure of the runtime procedure descriptor created by the loader
+ * for use by the static exception system.
+ */
+typedef struct runtime_pdr {
+ unsigned long adr; /* memory address of start of procedure */
+ long regmask; /* save register mask */
+ long regoffset; /* save register offset */
+ long fregmask; /* save floating point register mask */
+ long fregoffset; /* save floating point register offset */
+ long frameoffset; /* frame size */
+ short framereg; /* frame pointer register */
+ short pcreg; /* offset or reg of return pc */
+ long irpss; /* index into the runtime string table */
+ long reserved;
+ struct exception_info *exception_info;/* pointer to exception array */
+} RPDR, *pRPDR;
+#define cbRPDR sizeof(RPDR)
+#define rpdNil ((pRPDR) 0)
+
+/*
+ * Line Numbers
+ *
+ * Line Numbers are segregated from the normal symbols because they
+ * are [1] smaller , [2] are of no interest to your
+ * average loader, and [3] are never needed in the middle of normal
+ * scanning and therefore slow things down.
+ *
+ * By definition, the first LINER for any given procedure will have
+ * the first line of a procedure and represent the first address.
+ */
+
+typedef long LINER, *pLINER;
+#define lineNil ((pLINER)0)
+#define cbLINER sizeof(LINER)
+#define ilineNil -1
+
+
+
+/*
+ * The Symbol Structure (GFW, to those who Know!)
+ */
+
+typedef struct {
+ long iss; /* index into String Space of name */
+ long value; /* value of symbol */
+ unsigned st : 6; /* symbol type */
+ unsigned sc : 5; /* storage class - text, data, etc */
+ unsigned reserved : 1; /* reserved */
+ unsigned index : 20; /* index into sym/aux table */
+ } SYMR, *pSYMR;
+#define symNil ((pSYMR)0)
+#define cbSYMR sizeof(SYMR)
+#define isymNil -1
+#define indexNil 0xfffff
+#define issNil -1
+#define issNull 0
+
+
+/* The following converts a memory resident string to an iss.
+ * This hack is recognized in SbFIss, in sym.c of the debugger.
+ */
+#define IssFSb(sb) (0x80000000 | ((unsigned long)(sb)))
+
+/* E X T E R N A L S Y M B O L R E C O R D
+ *
+ * Same as the SYMR except it contains file context to determine where
+ * the index is.
+ */
+typedef struct {
+ unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */
+ unsigned cobol_main:1; /* symbol is a cobol main procedure */
+ unsigned weakext:1; /* symbol is weak external */
+ unsigned reserved:13; /* reserved for future use */
+ int ifd; /* where the iss and index fields point into */
+ SYMR asym; /* symbol for the external */
+ } EXTR, *pEXTR;
+#define extNil ((pEXTR)0)
+#define cbEXTR sizeof(EXTR)
+
+
+/* A U X I L L A R Y T Y P E I N F O R M A T I O N */
+
+/*
+ * Type Information Record
+ */
+typedef struct {
+ unsigned fBitfield : 1; /* set if bit width is specified */
+ unsigned continued : 1; /* indicates additional TQ info in next AUX */
+ unsigned bt : 6; /* basic type */
+ unsigned tq4 : 4;
+ unsigned tq5 : 4;
+ /* ---- 16 bit boundary ---- */
+ unsigned tq0 : 4;
+ unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */
+ unsigned tq2 : 4;
+ unsigned tq3 : 4;
+ } TIR, *pTIR;
+#define cbTIR sizeof(TIR)
+#define tiNil ((pTIR)0)
+#define itqMax 6
+
+/*
+ * Relative symbol record
+ *
+ * If the rfd field is 4095, the index field indexes into the global symbol
+ * table.
+ */
+
+typedef struct {
+ unsigned rfd : 12; /* index into the file indirect table */
+ unsigned index : 20; /* index int sym/aux/iss tables */
+ } RNDXR, *pRNDXR;
+#define cbRNDXR sizeof(RNDXR)
+#define rndxNil ((pRNDXR)0)
+
+/* dense numbers or sometimes called block numbers are stored in this type,
+ * a rfd of 0xffffffff is an index into the global table.
+ */
+typedef struct {
+ unsigned long rfd; /* index into the file table */
+ unsigned long index; /* index int sym/aux/iss tables */
+ } DNR, *pDNR;
+#define cbDNR sizeof(DNR)
+#define dnNil ((pDNR)0)
+
+
+
+/*
+ * Auxillary information occurs only if needed.
+ * It ALWAYS occurs in this order when present.
+
+ isymMac used by stProc only
+ TIR type info
+ TIR additional TQ info (if first TIR was not enough)
+ rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange,
+ btTypedef):
+ rsym.index == iaux for btSet or btRange
+ else rsym.index == isym
+ dimLow btRange, btSet
+ dimMac btRange, btSet
+ rndx0 As many as there are tq arrays
+ dimLow0
+ dimHigh0
+ ...
+ rndxMax-1
+ dimLowMax-1
+ dimHighMax-1
+ width in bits if (bit field), width in bits.
+ */
+#define cAuxMax (6 + (idimMax*3))
+
+/* a union of all possible info in the AUX universe */
+typedef union {
+ TIR ti; /* type information record */
+ RNDXR rndx; /* relative index into symbol table */
+ long dnLow; /* low dimension */
+ long dnHigh; /* high dimension */
+ long isym; /* symbol table index (end of proc) */
+ long iss; /* index into string space (not used) */
+ long width; /* width for non-default sized struc fields */
+ long count; /* count of ranges for variant arm */
+ } AUXU, *pAUXU;
+#define cbAUXU sizeof(AUXU)
+#define auxNil ((pAUXU)0)
+#define iauxNil -1
+
+
+/*
+ * Optimization symbols
+ *
+ * Optimization symbols contain some overlap information with the normal
+ * symbol table. In particular, the proc information
+ * is somewhat redundant but necessary to easily find the other information
+ * present.
+ *
+ * All of the offsets are relative to the beginning of the last otProc
+ */
+
+typedef struct {
+ unsigned ot: 8; /* optimization type */
+ unsigned value: 24; /* address where we are moving it to */
+ RNDXR rndx; /* points to a symbol or opt entry */
+ unsigned long offset; /* relative offset this occured */
+ } OPTR, *pOPTR;
+#define optNil ((pOPTR) 0)
+#define cbOPTR sizeof(OPTR)
+#define ioptNil -1
+
+/*
+ * File Indirect
+ *
+ * When a symbol is referenced across files the following procedure is used:
+ * 1) use the file index to get the File indirect entry.
+ * 2) use the file indirect entry to get the File descriptor.
+ * 3) add the sym index to the base of that file's sym table
+ *
+ */
+
+typedef long RFDT, *pRFDT;
+#define cbRFDT sizeof(RFDT)
+#define rfdNil -1
+
+/*
+ * The file indirect table in the mips loader is known as an array of FITs.
+ * This is done to keep the code in the loader readable in the area where
+ * these tables are merged. Note this is only a name change.
+ */
+typedef long FIT, *pFIT;
+#define cbFIT sizeof(FIT)
+#define ifiNil -1
+#define fiNil ((pFIT) 0)
+
+#ifdef _LANGUAGE_PASCAL
+#define ifdNil -1
+#define ilnNil -1
+#define ipdNil -1
+#define ilineNil -1
+#define isymNil -1
+#define indexNil 16#fffff
+#define issNil -1
+#define issNull 0
+#define itqMax 6
+#define iauxNil -1
+#define ioptNil -1
+#define rfdNil -1
+#define ifiNil -1
+#endif /* _LANGUAGE_PASCAL */
+
+
+/* Dense numbers
+ *
+ * Rather than use file index, symbol index pairs to represent symbols
+ * and globals, we use dense number so that they can be easily embeded
+ * in intermediate code and the programs that process them can
+ * use direct access tabls instead of hash table (which would be
+ * necesary otherwise because of the sparse name space caused by
+ * file index, symbol index pairs. Dense number are represented
+ * by RNDXRs.
+ */
+
+/*
+ * The following table defines the meaning of each SYM field as
+ * a function of the "st". (scD/B == scData OR scBss)
+ *
+ * Note: the value "isymMac" is used by symbols that have the concept
+ * of enclosing a block of related information. This value is the
+ * isym of the first symbol AFTER the end associated with the primary
+ * symbol. For example if a procedure was at isym==90 and had an
+ * isymMac==155, the associated end would be at isym==154, and the
+ * symbol at 155 would probably (although not necessarily) be the
+ * symbol for the next procedure. This allows rapid skipping over
+ * internal information of various sorts. "stEnd"s ALWAYS have the
+ * isym of the primary symbol that started the block.
+ *
+
+ST SC VALUE INDEX
+-------- ------ -------- ------
+stFile scText address isymMac
+stLabel scText address ---
+stGlobal scD/B address iaux
+stStatic scD/B address iaux
+stParam scAbs offset iaux
+stLocal scAbs offset iaux
+stProc scText address iaux (isymMac is first AUX)
+stStaticProc scText address iaux (isymMac is first AUX)
+
+stMember scNil ordinal --- (if member of enum)
+ (mipsread thinks the case below has a bit, not byte, offset.)
+stMember scNil byte offset iaux (if member of struct/union)
+stMember scBits bit offset iaux (bit field spec)
+
+stBlock scText address isymMac (text block)
+ (the code seems to think that rather than scNil, we see scInfo for
+ the two cases below.)
+stBlock scNil cb isymMac (struct/union member define)
+stBlock scNil cMembers isymMac (enum member define)
+
+ (New types added by SGI to simplify things:)
+stStruct scInfo cb isymMac (struct type define)
+stUnion scInfo cb isymMac (union type define)
+stEnum scInfo cMembers isymMac (enum type define)
+
+stEnd scText address isymStart
+stEnd scNil ------- isymStart (struct/union/enum)
+
+stTypedef scNil ------- iaux
+stRegReloc sc??? value old register number
+stForward sc??? new address isym to original symbol
+
+stConstant scInfo value --- (scalar)
+stConstant scInfo iss --- (complex, e.g. string)
+
+ *
+ */
+#endif
diff --git a/gnu/usr.bin/gdb/gdb/coff/symconst.h b/gnu/usr.bin/gdb/gdb/coff/symconst.h
new file mode 100644
index 000000000000..e4ed620131dc
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/coff/symconst.h
@@ -0,0 +1,175 @@
+/* Declarations of constants for internal format of MIPS ECOFF symbols.
+ Originally contributed by MIPS Computer Systems and Third Eye Software.
+ Changes contributed by Cygnus Support are in the public domain.
+
+ This file is just aggregated with the files that make up the GNU
+ release; it is not considered part of GAS, GDB, or other GNU
+ programs. */
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
+ * | MIPS Computer Systems, Inc. grants reproduction and use |
+ * | rights to all parties, PROVIDED that this comment is |
+ * | maintained in the copy. |
+ * |-----------------------------------------------------------|
+ */
+
+/* (C) Copyright 1984 by Third Eye Software, Inc.
+ *
+ * Third Eye Software, Inc. grants reproduction and use rights to
+ * all parties, PROVIDED that this comment is maintained in the copy.
+ *
+ * Third Eye makes no claims about the applicability of this
+ * symbol table to a particular use.
+ */
+
+/* glevels for field in FDR */
+#define GLEVEL_0 2
+#define GLEVEL_1 1
+#define GLEVEL_2 0 /* for upward compat reasons. */
+#define GLEVEL_3 3
+
+/* magic number fo symheader */
+#define magicSym 0x7009
+/* The Alpha uses this value instead, for some reason. */
+#define magicSym2 0x1992
+
+/* Language codes */
+#define langC 0
+#define langPascal 1
+#define langFortran 2
+#define langAssembler 3 /* one Assembley inst might map to many mach */
+#define langMachine 4
+#define langNil 5
+#define langAda 6
+#define langPl1 7
+#define langCobol 8
+#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */
+#define langCplusplus 9 /* FIXME: Collides with langStdc */
+#define langCplusplusV2 10 /* SGI addition */
+#define langMax 11 /* maximun allowed 32 -- 5 bits */
+
+/* The following are value definitions for the fields in the SYMR */
+
+/*
+ * Storage Classes
+ */
+
+#define scNil 0
+#define scText 1 /* text symbol */
+#define scData 2 /* initialized data symbol */
+#define scBss 3 /* un-initialized data symbol */
+#define scRegister 4 /* value of symbol is register number */
+#define scAbs 5 /* value of symbol is absolute */
+#define scUndefined 6 /* who knows? */
+#define scCdbLocal 7 /* variable's value is IN se->va.?? */
+#define scBits 8 /* this is a bit field */
+#define scCdbSystem 9 /* variable's value is IN CDB's address space */
+#define scDbx 9 /* overlap dbx internal use */
+#define scRegImage 10 /* register value saved on stack */
+#define scInfo 11 /* symbol contains debugger information */
+#define scUserStruct 12 /* address in struct user for current process */
+#define scSData 13 /* load time only small data */
+#define scSBss 14 /* load time only small common */
+#define scRData 15 /* load time only read only data */
+#define scVar 16 /* Var parameter (fortran,pascal) */
+#define scCommon 17 /* common variable */
+#define scSCommon 18 /* small common */
+#define scVarRegister 19 /* Var parameter in a register */
+#define scVariant 20 /* Variant record */
+#define scSUndefined 21 /* small undefined(external) data */
+#define scInit 22 /* .init section symbol */
+#define scBasedVar 23 /* Fortran or PL/1 ptr based var */
+#define scXData 24 /* exception handling data */
+#define scPData 25 /* Procedure section */
+#define scFini 26 /* .fini section */
+#define scMax 32
+
+
+/*
+ * Symbol Types
+ */
+
+#define stNil 0 /* Nuthin' special */
+#define stGlobal 1 /* external symbol */
+#define stStatic 2 /* static */
+#define stParam 3 /* procedure argument */
+#define stLocal 4 /* local variable */
+#define stLabel 5 /* label */
+#define stProc 6 /* " " Procedure */
+#define stBlock 7 /* beginnning of block */
+#define stEnd 8 /* end (of anything) */
+#define stMember 9 /* member (of anything - struct/union/enum */
+#define stTypedef 10 /* type definition */
+#define stFile 11 /* file name */
+#define stRegReloc 12 /* register relocation */
+#define stForward 13 /* forwarding address */
+#define stStaticProc 14 /* load time only static procs */
+#define stConstant 15 /* const */
+#define stStaParam 16 /* Fortran static parameters */
+ /* These new symbol types have been recently added to SGI machines. */
+#define stStruct 26 /* Beginning of block defining a struct type */
+#define stUnion 27 /* Beginning of block defining a union type */
+#define stEnum 28 /* Beginning of block defining an enum type */
+ /* Psuedo-symbols - internal to debugger */
+#define stStr 60 /* string */
+#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */
+#define stExpr 62 /* 2+2 vs. 4 */
+#define stType 63 /* post-coersion SER */
+#define stMax 64
+
+/* definitions for fields in TIR */
+
+/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */
+#define tqNil 0 /* bt is what you see */
+#define tqPtr 1 /* pointer */
+#define tqProc 2 /* procedure */
+#define tqArray 3 /* duh */
+#define tqFar 4 /* longer addressing - 8086/8 land */
+#define tqVol 5 /* volatile */
+#define tqConst 6 /* const */
+#define tqMax 8
+
+/* basic types as seen in ti.bt */
+#define btNil 0 /* undefined (also, enum members) */
+#define btAdr 1 /* address - integer same size as pointer */
+#define btChar 2 /* character */
+#define btUChar 3 /* unsigned character */
+#define btShort 4 /* short */
+#define btUShort 5 /* unsigned short */
+#define btInt 6 /* int */
+#define btUInt 7 /* unsigned int */
+#define btLong 8 /* long */
+#define btULong 9 /* unsigned long */
+#define btFloat 10 /* float (real) */
+#define btDouble 11 /* Double (real) */
+#define btStruct 12 /* Structure (Record) */
+#define btUnion 13 /* Union (variant) */
+#define btEnum 14 /* Enumerated */
+#define btTypedef 15 /* defined via a typedef, isymRef points */
+#define btRange 16 /* subrange of int */
+#define btSet 17 /* pascal sets */
+#define btComplex 18 /* fortran complex */
+#define btDComplex 19 /* fortran double complex */
+#define btIndirect 20 /* forward or unnamed typedef */
+#define btFixedDec 21 /* Fixed Decimal */
+#define btFloatDec 22 /* Float Decimal */
+#define btString 23 /* Varying Length Character String */
+#define btBit 24 /* Aligned Bit String */
+#define btPicture 25 /* Picture */
+#define btVoid 26 /* void */
+#define btLongLong 27 /* long long */
+#define btULongLong 28 /* unsigned long long */
+#define btMax 64
+
+#if (_MFG == _MIPS)
+/* optimization type codes */
+#define otNil 0
+#define otReg 1 /* move var to reg */
+#define otBlock 2 /* begin basic block */
+#define otProc 3 /* procedure */
+#define otInline 4 /* inline procedure */
+#define otEnd 5 /* whatever you started */
+#define otMax 6 /* KEEP UP TO DATE */
+#endif /* (_MFG == _MIPS) */
diff --git a/gnu/usr.bin/gdb/gdb/coffread.c b/gnu/usr.bin/gdb/gdb/coffread.c
new file mode 100644
index 000000000000..eb0905b867ac
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/coffread.c
@@ -0,0 +1,2071 @@
+/* Read coff symbol tables and convert to internal format, for GDB.
+ Contributed by David D. Johnson, Brown University (ddj@cs.brown.edu).
+ Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "breakpoint.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "gdb-stabs.h"
+#include "complaints.h"
+#include <obstack.h>
+
+#include <string.h>
+
+#include <time.h> /* For time_t in libbfd.h. */
+#include <sys/types.h> /* For time_t, if not in time.h. */
+#include "libbfd.h" /* FIXME secret internal data from BFD */
+#include "coff/internal.h" /* Internal format of COFF symbols in BFD */
+#include "libcoff.h" /* FIXME secret internal data from BFD */
+
+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 */
+
+ asection *stabsect; /* Section pointer for .stab section */
+ asection *stabstrsect; /* Section pointer for .stab section */
+ asection *stabindexsect; /* Section pointer for .stab.index section */
+ char *stabstrdata;
+};
+
+/* Translate an external name string into a user-visible name. */
+#define EXTERNAL_NAME(string, abfd) \
+ (string[0] == bfd_get_symbol_leading_char(abfd)? string+1: string)
+
+/* To be an sdb debug type, type must have at least a basic or primary
+ derived type. Using this rather than checking against T_NULL is
+ said to prevent core dumps if we try to operate on Michael Bloom
+ dbx-in-coff file. */
+
+#define SDB_TYPE(type) (BTYPE(type) | (type & N_TMASK))
+
+/*
+ * Convert from an sdb register number to an internal gdb register number.
+ * This should be defined in tm.h, if REGISTER_NAMES is not set up
+ * to map one to one onto the sdb register numbers.
+ */
+#ifndef SDB_REG_TO_REGNUM
+# define SDB_REG_TO_REGNUM(value) (value)
+#endif
+
+/* 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;
+
+/* 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;
+
+/* 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;
+
+/* Pointers to scratch storage, used for reading raw symbols and auxents. */
+
+static char *temp_sym;
+static char *temp_aux;
+
+/* Local variables that hold the shift and mask values for the
+ COFF file that we are currently reading. These come back to us
+ from BFD, and are referenced by their macro names, as well as
+ internally to the BTYPE, ISPTR, ISFCN, ISARY, ISTAG, and DECREF
+ macros from ../internalcoff.h . */
+
+static unsigned local_n_btmask;
+static unsigned local_n_btshft;
+static unsigned local_n_tmask;
+static unsigned local_n_tshift;
+
+#define N_BTMASK local_n_btmask
+#define N_BTSHFT local_n_btshft
+#define N_TMASK local_n_tmask
+#define N_TSHIFT local_n_tshift
+
+/* Local variables that hold the sizes in the file of various COFF structures.
+ (We only need to know this to read them from the file -- BFD will then
+ translate the data in them, into `internal_xxx' structs in the right
+ byte order, alignment, etc.) */
+
+static unsigned local_linesz;
+static unsigned local_symesz;
+static unsigned local_auxesz;
+
+
+/* Chain of typedefs of pointers to empty struct/union types.
+ They are chained thru the SYMBOL_VALUE_CHAIN. */
+
+static struct symbol *opaque_type_chain[HASHSIZE];
+
+#if 0
+/* The type of the function we are currently reading in. This is
+ used by define_symbol to record the type of arguments to a function. */
+
+struct type *in_function_type;
+#endif
+
+struct pending_block *pending_blocks;
+
+/* Complaints about various problems in the file being read */
+
+struct complaint ef_complaint =
+ {"Unmatched .ef symbol(s) ignored starting at symnum %d", 0, 0};
+
+struct complaint bf_no_aux_complaint =
+ {"`.bf' symbol %d has no aux entry", 0, 0};
+
+struct complaint ef_no_aux_complaint =
+ {"`.ef' symbol %d has no aux entry", 0, 0};
+
+struct complaint lineno_complaint =
+ {"Line number pointer %d lower than start of line numbers", 0, 0};
+
+struct complaint unexpected_type_complaint =
+ {"Unexpected type for symbol %s", 0, 0};
+
+struct complaint bad_sclass_complaint =
+ {"Bad n_sclass for symbol %s", 0, 0};
+
+struct complaint misordered_blocks_complaint =
+ {"Blocks out of order at address %x", 0, 0};
+
+struct complaint tagndx_bad_complaint =
+ {"Symbol table entry for %s has bad tagndx value", 0, 0};
+
+struct complaint eb_complaint =
+ {"Mismatched .eb symbol ignored starting at symnum %d", 0, 0};
+
+/* Simplified internal version of coff symbol table information */
+
+struct coff_symbol {
+ char *c_name;
+ int c_symnum; /* symbol number of this entry */
+ int c_naux; /* 0 if syment only, 1 if syment + auxent, etc */
+ long c_value;
+ int c_sclass;
+ int c_secnum;
+ unsigned int c_type;
+};
+
+static struct type *
+coff_read_struct_type PARAMS ((int, int, int));
+
+static struct type *
+decode_base_type PARAMS ((struct coff_symbol *, unsigned int,
+ union internal_auxent *));
+
+static struct type *
+decode_type PARAMS ((struct coff_symbol *, unsigned int,
+ union internal_auxent *));
+
+static struct type *
+decode_function_type PARAMS ((struct coff_symbol *, unsigned int,
+ union internal_auxent *));
+
+static struct type *
+coff_read_enum_type PARAMS ((int, int, int));
+
+static struct symbol *
+process_coff_symbol PARAMS ((struct coff_symbol *, union internal_auxent *,
+ struct objfile *));
+
+static void
+patch_opaque_types PARAMS ((struct symtab *));
+
+static void
+patch_type PARAMS ((struct type *, struct type *));
+
+static void
+enter_linenos PARAMS ((long, int, int));
+
+static void
+free_linetab PARAMS ((void));
+
+static int
+init_lineno PARAMS ((int, long, int));
+
+static char *
+getfilename PARAMS ((union internal_auxent *));
+
+static char *
+getsymname PARAMS ((struct internal_syment *));
+
+static void
+free_stringtab PARAMS ((void));
+
+static int
+init_stringtab PARAMS ((int, long));
+
+static void
+read_one_sym PARAMS ((struct coff_symbol *, struct internal_syment *,
+ union internal_auxent *));
+
+static void
+read_coff_symtab PARAMS ((long, int, struct objfile *));
+
+static void
+find_linenos PARAMS ((bfd *, sec_ptr, PTR));
+
+static void
+coff_symfile_init PARAMS ((struct objfile *));
+
+static void
+coff_new_init PARAMS ((struct objfile *));
+
+static void
+coff_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+coff_symfile_finish PARAMS ((struct objfile *));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type));
+
+static void
+coff_end_symtab PARAMS ((struct objfile *));
+
+static void
+complete_symtab PARAMS ((char *, CORE_ADDR, unsigned int));
+
+static void
+coff_start_symtab PARAMS ((void));
+
+static void
+coff_record_line PARAMS ((int, CORE_ADDR));
+
+static struct type *
+coff_alloc_type PARAMS ((int));
+
+static struct type **
+coff_lookup_type PARAMS ((int));
+
+
+static void
+coff_locate_sections PARAMS ((bfd *, asection *, PTR));
+
+/* We are called once per section from coff_symfile_read. We
+ need to examine each section we are passed, check to see
+ if it is something we are interested in processing, and
+ if so, stash away some access information for the section.
+
+ FIXME: The section names should not be hardwired strings (what
+ should they be? I don't think most object file formats have enough
+ section flags to specify what kind of debug section it is
+ -kingdon). */
+
+static void
+coff_locate_sections (ignore_abfd, sectp, csip)
+ bfd *ignore_abfd;
+ asection *sectp;
+ PTR csip;
+{
+ register struct coff_symfile_info *csi;
+
+ csi = (struct coff_symfile_info *) csip;
+ if (STREQ (sectp->name, ".stab"))
+ {
+ csi->stabsect = sectp;
+ }
+ else if (STREQ (sectp->name, ".stabstr"))
+ {
+ csi->stabstrsect = sectp;
+ }
+ else if (STREQ (sectp->name, ".stab.index"))
+ {
+ csi->stabindexsect = sectp;
+ }
+}
+
+/* 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 (index /* is still */ >= type_vector_length) {
+ type_vector_length = index * 2;
+ }
+ type_vector = (struct type **)
+ xrealloc ((char *) type_vector,
+ type_vector_length * sizeof (struct type *));
+ memset (&type_vector[old_vector_length], 0,
+ (type_vector_length - old_vector_length) * sizeof(struct type *));
+ }
+ return &type_vector[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 == NULL)
+ {
+ type = alloc_type (current_objfile);
+ *type_addr = type;
+ }
+ return type;
+}
+
+/* Record a line number entry for line LINE at address PC.
+ FIXME: Use record_line instead. */
+
+static void
+coff_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 ((char *) 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;
+}
+
+/* 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
+coff_start_symtab ()
+{
+ start_symtab (
+ /* We fill in the filename later. start_symtab
+ puts this pointer into last_source file and in
+ coff_end_symtab we assume we can free() it.
+ FIXME: leaks memory. */
+ savestring ("", 0),
+ /* We never know the directory name for COFF. */
+ NULL,
+ /* The start address is irrelevant, since we set
+ last_source_start_addr in coff_end_symtab. */
+ 0);
+
+ /* Initialize the source file line number information for this file. */
+
+ if (line_vector) /* Unlikely, but maybe possible? */
+ free ((PTR)line_vector);
+ 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 (current_objfile -> ei.entry_point >= cur_src_start_addr &&
+ current_objfile -> ei.entry_point < cur_src_end_addr)
+ {
+ current_objfile -> ei.entry_file_lowpc = cur_src_start_addr;
+ current_objfile -> ei.entry_file_highpc = 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
+coff_end_symtab (objfile)
+ struct objfile *objfile;
+{
+ struct symtab *symtab;
+
+ last_source_start_addr = cur_src_start_addr;
+
+ /* For no good reason, this file stores the number of entries in a
+ separate variable instead of in line_vector->nitems. Fix it. */
+ if (line_vector)
+ line_vector->nitems = line_vector_index;
+
+ /* For COFF, we only have one subfile, so we can just look at
+ subfiles and not worry about there being other elements in the
+ chain. We fill in various fields now because we didn't know them
+ before (or because doing it now is simply an artifact of how this
+ file used to be written). */
+ subfiles->line_vector = line_vector;
+ subfiles->name = last_source_file;
+
+ /* sort_pending is needed for amdcoff, at least.
+ sort_linevec is needed for the SCO compiler. */
+ symtab = end_symtab (cur_src_end_addr, 1, 1, objfile, 0);
+
+ if (symtab != NULL)
+ free_named_symtabs (symtab->filename);
+
+ /* Reinitialize for beginning of new file. */
+ line_vector = 0;
+ line_vector_length = -1;
+ last_source_file = NULL;
+}
+
+static void
+record_minimal_symbol (name, address, type)
+ char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type type;
+{
+ /* We don't want TDESC entry points in the minimal symbol table */
+ if (name[0] == '@') return;
+
+ prim_record_minimal_symbol (savestring (name, strlen (name)), address, type);
+}
+
+/* coff_symfile_init ()
+ is the coff-specific initialization routine for reading symbols.
+ It is passed a struct objfile 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). */
+
+static int text_bfd_scnum;
+
+static void
+coff_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ asection *section, *strsection;
+ bfd *abfd = objfile->obfd;
+
+ /* Allocate struct to keep track of stab reading. */
+ objfile->sym_stab_info = (PTR)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+
+ memset ((PTR) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info));
+
+ /* Allocate struct to keep track of the symfile */
+ objfile -> sym_private = xmmalloc (objfile -> md,
+ sizeof (struct coff_symfile_info));
+
+ memset (objfile->sym_private, 0, sizeof (struct coff_symfile_info));
+
+ init_entry_point_info (objfile);
+
+ /* Save the section number for the text section */
+ section = bfd_get_section_by_name (abfd, ".text");
+ if (section)
+ text_bfd_scnum = section->index;
+ else
+ text_bfd_scnum = -1;
+}
+
+/* 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. */
+
+/* ARGSUSED */
+static void
+find_linenos (abfd, asect, vpinfo)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR 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 * local_linesz;
+
+ 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;
+}
+
+
+/* The BFD for this file -- only good while we're actively reading
+ symbols into a psymtab or a symtab. */
+
+static bfd *symfile_bfd;
+
+/* 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! */
+
+/* ARGSUSED */
+static void
+coff_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ struct coff_symfile_info *info;
+ struct dbx_symfile_info *dbxinfo;
+ bfd *abfd = objfile->obfd;
+ coff_data_type *cdata = coff_data (abfd);
+ char *name = bfd_get_filename (abfd);
+ int desc;
+ register int val;
+ int num_symbols;
+ int symtab_offset;
+ int stringtab_offset;
+ struct cleanup *back_to;
+ int stabsize, stabstrsize;
+
+ info = (struct coff_symfile_info *) objfile -> sym_private;
+ dbxinfo = (struct dbx_symfile_info *) objfile->sym_stab_info;
+ 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 = cdata->sym_filepos; /* Symbol table file offset */
+ stringtab_offset = symtab_offset + /* String table file offset */
+ num_symbols * cdata->local_symesz;
+
+ /* Set a few file-statics that give us specific information about
+ the particular COFF file format we're reading. */
+ local_linesz = cdata->local_linesz;
+ local_n_btmask = cdata->local_n_btmask;
+ local_n_btshft = cdata->local_n_btshft;
+ local_n_tmask = cdata->local_n_tmask;
+ local_n_tshift = cdata->local_n_tshift;
+ local_linesz = cdata->local_linesz;
+ local_symesz = cdata->local_symesz;
+ local_auxesz = cdata->local_auxesz;
+
+ /* Allocate space for raw symbol and aux entries, based on their
+ space requirements as reported by BFD. */
+ temp_sym = (char *) xmalloc
+ (cdata->local_symesz + cdata->local_auxesz);
+ temp_aux = temp_sym + cdata->local_symesz;
+ back_to = make_cleanup (free_current_contents, &temp_sym);
+/* End of warning */
+
+ /* 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, (PTR) info);
+
+ make_cleanup (free_linetab, 0);
+ 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. */
+
+ make_cleanup (free_stringtab, 0);
+ val = init_stringtab (desc, stringtab_offset);
+ if (val < 0)
+ error ("\"%s\": can't get string table", name);
+
+ init_minimal_symbol_collection ();
+ make_cleanup (discard_minimal_symbols, 0);
+
+ /* Now that the executable file is positioned at symbol table,
+ process it and define symbols accordingly. */
+
+ read_coff_symtab ((long)symtab_offset, num_symbols, objfile);
+
+ /* Sort symbols alphabetically within each block. */
+
+ sort_all_symtab_syms ();
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ bfd_map_over_sections (abfd, coff_locate_sections, (PTR) info);
+
+ if (info->stabsect)
+ {
+ /* FIXME: dubious. Why can't we use something normal like
+ bfd_get_section_contents? */
+ fseek ((FILE *) abfd->iostream, abfd->where, 0);
+
+ stabsize = bfd_section_size (abfd, info->stabsect);
+ stabstrsize = bfd_section_size (abfd, info->stabstrsect);
+
+ coffstab_build_psymtabs (objfile,
+ section_offsets,
+ mainline,
+ info->stabsect->filepos, stabsize,
+ info->stabstrsect->filepos, stabstrsize);
+ }
+
+ do_cleanups (back_to);
+}
+
+static void
+coff_new_init (ignore)
+ struct objfile *ignore;
+{
+}
+
+/* Perform any local cleanups required when we are done with a particular
+ objfile. I.E, we are in the process of discarding all symbol information
+ for an objfile, freeing up all memory held for it, and unlinking the
+ objfile struct from the global list of known objfiles. */
+
+static void
+coff_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_private != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_private);
+ }
+}
+
+
+/* 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 (symtab_offset, nsyms, objfile)
+ long symtab_offset;
+ int nsyms;
+ struct objfile *objfile;
+{
+ FILE *stream;
+ register struct context_stack *new;
+ struct coff_symbol coff_symbol;
+ register struct coff_symbol *cs = &coff_symbol;
+ static struct internal_syment main_sym;
+ static union internal_auxent main_aux;
+ struct coff_symbol fcn_cs_saved;
+ static struct internal_syment fcn_sym_saved;
+ static union internal_auxent fcn_aux_saved;
+ struct symtab *s;
+
+ /* 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 = 0;
+ int fcn_first_line = 0;
+ int fcn_last_line = 0;
+ int fcn_start_addr = 0;
+ long fcn_line_ptr = 0;
+ int val;
+
+ stream = bfd_cache_lookup(objfile->obfd);
+ if (!stream)
+ perror_with_name(objfile->name);
+
+ /* Work around a stdio bug in SunOS4.1.1 (this makes me nervous....
+ it's hard to know I've really worked around it. The fix should be
+ harmless, anyway). The symptom of the bug is that the first
+ fread (in read_one_sym), will (in my example) actually get data
+ from file offset 268, when the fseek was to 264 (and ftell shows
+ 264). This causes all hell to break loose. I was unable to
+ reproduce this on a short test program which operated on the same
+ file, performing (I think) the same sequence of operations.
+
+ It stopped happening when I put in this rewind().
+
+ FIXME: Find out if this has been reported to Sun, whether it has
+ been fixed in a later release, etc. */
+
+ rewind (stream);
+
+ /* Position to read the symbol table. */
+ val = fseek (stream, (long)symtab_offset, 0);
+ if (val < 0)
+ perror_with_name (objfile->name);
+
+ current_objfile = objfile;
+ nlist_stream_global = stream;
+ nlist_nsyms_global = nsyms;
+ last_source_file = NULL;
+ memset (opaque_type_chain, 0, sizeof opaque_type_chain);
+
+ if (type_vector) /* Get rid of previous one */
+ free ((PTR)type_vector);
+ type_vector_length = 160;
+ type_vector = (struct type **)
+ xmalloc (type_vector_length * sizeof (struct type *));
+ memset (type_vector, 0, type_vector_length * sizeof (struct type *));
+
+ coff_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)
+ coff_end_symtab (objfile);
+
+ coff_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 && SDB_TYPE (cs->c_type)
+ && 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 all functions -- external and static -- in minsyms. */
+ record_minimal_symbol (cs->c_name, cs->c_value, mst_text);
+
+ 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:
+ complain (&bad_sclass_complaint, cs->c_name);
+ 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;
+ if (cs->c_naux > 0)
+ filestring = getfilename (&main_aux);
+ else
+ filestring = "";
+
+ /*
+ * Complete symbol table for last object file
+ * containing debugging information.
+ */
+ if (last_source_file)
+ {
+ coff_end_symtab (objfile);
+ coff_start_symtab ();
+ }
+ in_source_file = 1;
+ break;
+
+ case C_STAT:
+ if (cs->c_name[0] == '.') {
+ if (STREQ (cs->c_name, ".text")) {
+ /* FIXME: don't wire in ".text" as section name
+ or symbol name! */
+ 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 (!SDB_TYPE (cs->c_type)
+ && cs->c_name[0] == 'L'
+ && (strncmp (cs->c_name, "LI%", 3) == 0
+ || strncmp (cs->c_name, "LF%", 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:
+ /* Record external symbols in minsyms if we don't have debug
+ info for them. FIXME, this is probably the wrong thing
+ to do. Why don't we record them even if we do have
+ debug symbol info? What really belongs in the minsyms
+ anyway? Fred!?? */
+ if (!SDB_TYPE (cs->c_type)) {
+ /* FIXME: This is BOGUS Will Robinson!
+ Coff should provide the SEC_CODE flag for executable sections,
+ then if we could look up sections by section number we
+ could see if the flags indicate SEC_CODE. If so, then
+ record this symbol as a function in the minimal symbol table.
+ But why are absolute syms recorded as functions, anyway? */
+ if (cs->c_secnum <= text_bfd_scnum+1) {/* text or abs */
+ record_minimal_symbol (cs->c_name, cs->c_value,
+ mst_text);
+ break;
+ } else {
+ record_minimal_symbol (cs->c_name, cs->c_value,
+ mst_data);
+ break;
+ }
+ }
+ process_coff_symbol (cs, &main_aux, objfile);
+ break;
+
+ case C_FCN:
+ if (STREQ (cs->c_name, ".bf"))
+ {
+ 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 '{' } */
+ if (cs->c_naux != 1)
+ complain (&bf_no_aux_complaint, cs->c_symnum);
+ fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno;
+
+ /* Might want to check that locals are 0 and
+ context_stack_depth is zero, and complain if not. */
+
+ depth = 0;
+ new = push_context (depth, fcn_start_addr);
+ fcn_cs_saved.c_name = getsymname (&fcn_sym_saved);
+ new->name = process_coff_symbol (&fcn_cs_saved,
+ &fcn_aux_saved, objfile);
+ }
+ else if (STREQ (cs->c_name, ".ef"))
+ {
+ /* 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 = pop_context ();
+ /* Stack must be empty now. */
+ if (context_stack_depth > 0 || new == NULL)
+ {
+ complain (&ef_complaint, cs->c_symnum);
+ within_function = 0;
+ break;
+ }
+ if (cs->c_naux != 1)
+ {
+ complain (&ef_no_aux_complaint, cs->c_symnum);
+ fcn_last_line = 0x7FFFFFFF;
+ }
+ else
+ {
+ 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
+ objfile
+ );
+ within_function = 0;
+ }
+ break;
+
+ case C_BLOCK:
+ if (STREQ (cs->c_name, ".bb"))
+ {
+ push_context (++depth, cs->c_value);
+ }
+ else if (STREQ (cs->c_name, ".eb"))
+ {
+ new = pop_context ();
+ if (depth-- != new->depth)
+ {
+ complain (&eb_complaint, symnum);
+ break;
+ }
+ if (local_symbols && context_stack_depth > 0)
+ {
+ /* Make a block for the local symbols within. */
+ finish_block (0, &local_symbols, new->old_blocks,
+ new->start_addr, cs->c_value, objfile);
+ }
+ /* Now pop locals of block just finished. */
+ local_symbols = new->locals;
+ }
+ break;
+
+ default:
+ process_coff_symbol (cs, &main_aux, objfile);
+ break;
+ }
+ }
+
+ if (last_source_file)
+ coff_end_symtab (objfile);
+
+ /* Patch up any opaque types (references to types that are not defined
+ in the file where they are referenced, e.g. "struct foo *bar"). */
+ ALL_OBJFILE_SYMTABS (objfile, s)
+ patch_opaque_types (s);
+
+ current_objfile = NULL;
+}
+
+/* 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
+
+/* Read the next symbol, swap it, and return it in both internal_syment
+ form, and coff_symbol form. Also return its first auxent, if any,
+ in internal_auxent form, and skip any other auxents. */
+
+static void
+read_one_sym (cs, sym, aux)
+ register struct coff_symbol *cs;
+ register struct internal_syment *sym;
+ register union internal_auxent *aux;
+{
+ int i;
+
+ cs->c_symnum = symnum;
+ fread (temp_sym, local_symesz, 1, nlist_stream_global);
+ bfd_coff_swap_sym_in (symfile_bfd, temp_sym, (char *)sym);
+ cs->c_naux = sym->n_numaux & 0xff;
+ if (cs->c_naux >= 1)
+ {
+ fread (temp_aux, local_auxesz, 1, nlist_stream_global);
+ bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass,
+ (char *)aux);
+ /* If more than one aux entry, read past it (only the first aux
+ is important). */
+ for (i = 1; i < cs->c_naux; i++)
+ fread (temp_aux, local_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;
+ if (!SDB_TYPE (cs->c_type))
+ cs->c_type = 0;
+
+ symnum += 1 + cs->c_naux;
+}
+
+/* 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];
+
+ free_stringtab ();
+
+ if (lseek (chan, offset, 0) < 0)
+ return -1;
+
+ val = myread (chan, (char *)lengthbuf, sizeof lengthbuf);
+ length = bfd_h_get_32 (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 lengthbuf || length < sizeof lengthbuf)
+ return 0;
+
+ stringtab = (char *) xmalloc (length);
+ memcpy (stringtab, &length, sizeof length);
+ if (length == sizeof length) /* Empty table -- just the count */
+ return 0;
+
+ val = myread (chan, stringtab + sizeof lengthbuf, length - sizeof lengthbuf);
+ if (val != length - sizeof lengthbuf || stringtab[length - 1] != '\0')
+ return -1;
+
+ return 0;
+}
+
+static void
+free_stringtab ()
+{
+ if (stringtab)
+ free (stringtab);
+ stringtab = NULL;
+}
+
+static char *
+getsymname (symbol_entry)
+ struct internal_syment *symbol_entry;
+{
+ static char buffer[SYMNMLEN+1];
+ char *result;
+
+ if (symbol_entry->_n._n_n._n_zeroes == 0)
+ {
+ result = stringtab + symbol_entry->_n._n_n._n_offset;
+ }
+ else
+ {
+ strncpy (buffer, symbol_entry->_n._n_name, SYMNMLEN);
+ buffer[SYMNMLEN] = '\0';
+ result = buffer;
+ }
+ return result;
+}
+
+/* Extract the file name from the aux entry of a C_FILE symbol. Return
+ only the last component of the name. Result is in static storage and
+ is only good for temporary use. */
+
+static char *
+getfilename (aux_entry)
+ union internal_auxent *aux_entry;
+{
+ static char buffer[BUFSIZ];
+ register char *temp;
+ char *result;
+
+ if (aux_entry->x_file.x_n.x_zeroes == 0)
+ strcpy (buffer, stringtab + aux_entry->x_file.x_n.x_offset);
+ else
+ {
+ strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN);
+ buffer[FILNMLEN] = '\0';
+ }
+ result = buffer;
+ if ((temp = strrchr (result, '/')) != NULL)
+ result = temp + 1;
+ return (result);
+}
+
+/* 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. Leave them in
+ external (unswapped) format in memory; we'll swap them as we enter
+ them into GDB's data structures. */
+
+static int
+init_lineno (chan, offset, size)
+ int chan;
+ long offset;
+ int size;
+{
+ int val;
+
+ linetab_offset = offset;
+ linetab_size = size;
+
+ free_linetab();
+
+ if (size == 0)
+ return 0;
+
+ if (lseek (chan, offset, 0) < 0)
+ return -1;
+
+ /* Allocate the desired table, plus a sentinel */
+ linetab = (char *) xmalloc (size + local_linesz);
+
+ val = myread (chan, linetab, size);
+ if (val != size)
+ return -1;
+
+ /* Terminate it with an all-zero sentinel record */
+ memset (linetab + size, 0, local_linesz);
+
+ return 0;
+}
+
+static void
+free_linetab ()
+{
+ if (linetab)
+ free (linetab);
+ linetab = NULL;
+}
+
+#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 internal_lineno lptr;
+
+ if (file_offset < linetab_offset)
+ {
+ complain (&lineno_complaint, file_offset);
+ if (file_offset > linetab_size) /* Too big to be an offset? */
+ return;
+ file_offset += linetab_offset; /* Try reading at that linetab offset */
+ }
+
+ rawptr = &linetab[file_offset - linetab_offset];
+
+ /* skip first line entry for each function */
+ rawptr += local_linesz;
+ /* line numbers start at one for the first line of the function */
+ first_line--;
+
+ for (;;) {
+ bfd_coff_swap_lineno_in (symfile_bfd, rawptr, &lptr);
+ rawptr += local_linesz;
+ /* The next function, or the sentinel, will have L_LNNO32 zero; we exit. */
+ if (L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line)
+ coff_record_line (first_line + L_LNNO32 (&lptr), lptr.l_addr.l_paddr);
+ else
+ break;
+ }
+}
+
+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 *) TYPE_ALLOC (target, field_size);
+
+ memcpy (TYPE_FIELDS (target), TYPE_FIELDS (real_target), field_size);
+
+ if (TYPE_NAME (real_target))
+ {
+ if (TYPE_NAME (target))
+ free (TYPE_NAME (target));
+ TYPE_NAME (target) = concat (TYPE_NAME (real_target), NULL);
+ }
+}
+
+/* Patch up all appropriate typedef symbols in the opaque_type_chains
+ so that they can be used to print out opaque data structures properly. */
+
+static void
+patch_opaque_types (s)
+ struct symtab *s;
+{
+ register struct block *b;
+ register int i;
+ register struct symbol *real_sym;
+
+ /* Go through the per-file symbols only */
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--)
+ {
+ /* 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] &&
+ STREQ (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);
+ }
+ }
+ }
+ }
+}
+
+static struct symbol *
+process_coff_symbol (cs, aux, objfile)
+ register struct coff_symbol *cs;
+ register union internal_auxent *aux;
+ struct objfile *objfile;
+{
+ register struct symbol *sym
+ = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ char *name;
+ struct type *temptype;
+
+ memset (sym, 0, sizeof (struct symbol));
+ name = cs->c_name;
+ name = EXTERNAL_NAME (name, objfile->obfd);
+ SYMBOL_NAME (sym) = obstack_copy0 (&objfile->symbol_obstack, name,
+ strlen (name));
+
+ /* default assumptions */
+ SYMBOL_VALUE (sym) = cs->c_value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+ if (ISFCN (cs->c_type))
+ {
+#if 0
+ /* FIXME: This has NOT been tested. The DBX version has.. */
+ /* Generate a template for the type of this function. The
+ types of the arguments will be added as we read the symbol
+ table. */
+ struct type *new = (struct type *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct type));
+
+ memcpy (new, lookup_function_type (decode_function_type (cs, cs->c_type, aux)),
+ sizeof(struct type));
+ SYMBOL_TYPE (sym) = new;
+ in_function_type = SYMBOL_TYPE(sym);
+#else
+ SYMBOL_TYPE(sym) =
+ lookup_function_type (decode_function_type (cs, cs->c_type, aux));
+#endif
+
+ 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;
+
+#ifdef C_GLBLREG /* AMD coff */
+ case C_GLBLREG:
+#endif
+ case C_REG:
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) = SDB_REG_TO_REGNUM(cs->c_value);
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case C_LABEL:
+ break;
+
+ case C_ARG:
+ SYMBOL_CLASS (sym) = LOC_ARG;
+#if 0
+ /* FIXME: This has not been tested. */
+ /* Add parameter to function. */
+ add_param_to_type(&in_function_type,sym);
+#endif
+ add_symbol_to_list (sym, &local_symbols);
+#if !defined (BELIEVE_PCC_PROMOTION) && (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ /* If PCC says a parameter is a short or a char,
+ aligned on an int boundary, realign it to the "little end"
+ of the int. */
+ temptype = lookup_fundamental_type (current_objfile, FT_INTEGER);
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT
+ && 0 == SYMBOL_VALUE (sym) % TYPE_LENGTH (temptype))
+ {
+ SYMBOL_VALUE (sym) += TYPE_LENGTH (temptype)
+ - TYPE_LENGTH (SYMBOL_TYPE (sym));
+ }
+#endif
+ break;
+
+ case C_REGPARM:
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) = SDB_REG_TO_REGNUM(cs->c_value);
+ add_symbol_to_list (sym, &local_symbols);
+#if !defined (BELIEVE_PCC_PROMOTION)
+ /* FIXME: This should retain the current type, since it's just
+ a register value. gnu@adobe, 26Feb93 */
+ /* If PCC says a parameter is a short or a char,
+ it is really an int. */
+ temptype = lookup_fundamental_type (current_objfile, FT_INTEGER);
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (temptype)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT)
+ {
+ SYMBOL_TYPE (sym) = TYPE_UNSIGNED (SYMBOL_TYPE (sym))
+ ? lookup_fundamental_type (current_objfile,
+ FT_UNSIGNED_INTEGER)
+ : temptype;
+ }
+#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_NAME (SYMBOL_TYPE (sym)) = concat (SYMBOL_NAME (sym), NULL);
+
+ /* Keep track of any type which points to empty structured type,
+ so it can be filled from a definition from another file. A
+ simple forward reference (TYPE_CODE_UNDEF) is not an
+ empty structured type, though; the forward references
+ work themselves out via the magic of coff_lookup_type. */
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR &&
+ TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0 &&
+ TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) !=
+ TYPE_CODE_UNDEF)
+ {
+ 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;
+
+ /* Some compilers try to be helpful by inventing "fake"
+ names for anonymous enums, structures, and unions, like
+ "~0fake" or ".0fake". Thanks, but no thanks... */
+ if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0)
+ if (SYMBOL_NAME(sym) != NULL
+ && *SYMBOL_NAME(sym) != '~'
+ && *SYMBOL_NAME(sym) != '.')
+ TYPE_TAG_NAME (SYMBOL_TYPE (sym)) =
+ concat (SYMBOL_NAME (sym), NULL);
+
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ default:
+ break;
+ }
+ }
+ return sym;
+}
+
+/* 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 union internal_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, *index_type, *range_type;
+
+ /* Define an array type. */
+ /* auxent refers to array, not base type */
+ if (aux->x_sym.x_tagndx.l == 0)
+ cs->c_naux = 0;
+
+ /* 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;
+
+ base_type = decode_type (cs, new_c_type, aux);
+ index_type = lookup_fundamental_type (current_objfile, FT_INTEGER);
+ range_type =
+ create_range_type ((struct type *) NULL, index_type, 0, n - 1);
+ type =
+ create_array_type ((struct type *) NULL, base_type, range_type);
+ }
+ return type;
+ }
+
+ /* Reference to existing type. This only occurs with the
+ struct, union, and enum types. EPI a29k coff
+ fakes us out by producing aux entries with a nonzero
+ x_tagndx for definitions of structs, unions, and enums, so we
+ have to check the c_sclass field. SCO 3.2v4 cc gets confused
+ with pointers to pointers to defined structs, and generates
+ negative x_tagndx fields. */
+ if (cs->c_naux > 0 && aux->x_sym.x_tagndx.l != 0)
+ {
+ if (cs->c_sclass != C_STRTAG
+ && cs->c_sclass != C_UNTAG
+ && cs->c_sclass != C_ENTAG
+ && aux->x_sym.x_tagndx.l >= 0)
+ {
+ type = coff_alloc_type (aux->x_sym.x_tagndx.l);
+ return type;
+ } else {
+ complain (&tagndx_bad_complaint, cs->c_name);
+ /* And fall through to decode_base_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 union internal_auxent *aux;
+{
+ if (aux->x_sym.x_tagndx.l == 0)
+ cs->c_naux = 0; /* auxent refers to function, not base type */
+
+ return decode_type (cs, DECREF (c_type), aux);
+}
+
+/* basic C types */
+
+static
+struct type *
+decode_base_type (cs, c_type, aux)
+ register struct coff_symbol *cs;
+ unsigned int c_type;
+ register union internal_auxent *aux;
+{
+ struct type *type;
+
+ switch (c_type)
+ {
+ case T_NULL:
+ /* shows up with "void (*foo)();" structure members */
+ return lookup_fundamental_type (current_objfile, FT_VOID);
+
+#if 0
+/* DGUX actually defines both T_ARG and T_VOID to the same value. */
+#ifdef T_ARG
+ case T_ARG:
+ /* Shows up in DGUX, I think. Not sure where. */
+ return lookup_fundamental_type (current_objfile, FT_VOID); /* shouldn't show up here */
+#endif
+#endif /* 0 */
+
+#ifdef T_VOID
+ case T_VOID:
+ /* Intel 960 COFF has this symbol and meaning. */
+ return lookup_fundamental_type (current_objfile, FT_VOID);
+#endif
+
+ case T_CHAR:
+ return lookup_fundamental_type (current_objfile, FT_CHAR);
+
+ case T_SHORT:
+ return lookup_fundamental_type (current_objfile, FT_SHORT);
+
+ case T_INT:
+ return lookup_fundamental_type (current_objfile, FT_INTEGER);
+
+ case T_LONG:
+ return lookup_fundamental_type (current_objfile, FT_LONG);
+
+ case T_FLOAT:
+ return lookup_fundamental_type (current_objfile, FT_FLOAT);
+
+ case T_DOUBLE:
+ return lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+
+ case T_STRUCT:
+ if (cs->c_naux != 1)
+ {
+ /* anonymous structure type */
+ type = coff_alloc_type (cs->c_symnum);
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ TYPE_NAME (type) = NULL;
+ /* This used to set the tag to "<opaque>". But I think setting it
+ to NULL is right, and the printing code can print it as
+ "struct {...}". */
+ TYPE_TAG_NAME (type) = NULL;
+ INIT_CPLUS_SPECIFIC(type);
+ TYPE_LENGTH (type) = 0;
+ TYPE_FIELDS (type) = 0;
+ TYPE_NFIELDS (type) = 0;
+ }
+ else
+ {
+ type = coff_read_struct_type (cs->c_symnum,
+ aux->x_sym.x_misc.x_lnsz.x_size,
+ aux->x_sym.x_fcnary.x_fcn.x_endndx.l);
+ }
+ return type;
+
+ case T_UNION:
+ if (cs->c_naux != 1)
+ {
+ /* anonymous union type */
+ type = coff_alloc_type (cs->c_symnum);
+ TYPE_NAME (type) = NULL;
+ /* This used to set the tag to "<opaque>". But I think setting it
+ to NULL is right, and the printing code can print it as
+ "union {...}". */
+ TYPE_TAG_NAME (type) = NULL;
+ INIT_CPLUS_SPECIFIC(type);
+ TYPE_LENGTH (type) = 0;
+ TYPE_FIELDS (type) = 0;
+ TYPE_NFIELDS (type) = 0;
+ }
+ else
+ {
+ type = coff_read_struct_type (cs->c_symnum,
+ aux->x_sym.x_misc.x_lnsz.x_size,
+ aux->x_sym.x_fcnary.x_fcn.x_endndx.l);
+ }
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ return type;
+
+ case T_ENUM:
+ if (cs->c_naux != 1)
+ {
+ /* anonymous enum type */
+ type = coff_alloc_type (cs->c_symnum);
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_NAME (type) = NULL;
+ /* This used to set the tag to "<opaque>". But I think setting it
+ to NULL is right, and the printing code can print it as
+ "enum {...}". */
+ TYPE_TAG_NAME (type) = NULL;
+ TYPE_LENGTH (type) = 0;
+ TYPE_FIELDS (type) = 0;
+ TYPE_NFIELDS(type) = 0;
+ }
+ else
+ {
+ type = coff_read_enum_type (cs->c_symnum,
+ aux->x_sym.x_misc.x_lnsz.x_size,
+ aux->x_sym.x_fcnary.x_fcn.x_endndx.l);
+ }
+ return type;
+
+ case T_MOE:
+ /* shouldn't show up here */
+ break;
+
+ case T_UCHAR:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+
+ case T_USHORT:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
+
+ case T_UINT:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+
+ case T_ULONG:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
+ }
+ complain (&unexpected_type_complaint, cs->c_name);
+ return lookup_fundamental_type (current_objfile, FT_VOID);
+}
+
+/* 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 *
+coff_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;
+ struct coff_symbol member_sym;
+ register struct coff_symbol *ms = &member_sym;
+ struct internal_syment sub_sym;
+ union internal_auxent sub_aux;
+ int done = 0;
+
+ type = coff_alloc_type (index);
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ INIT_CPLUS_SPECIFIC(type);
+ 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 = EXTERNAL_NAME (name, current_objfile->obfd);
+
+ 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 *)
+ TYPE_ALLOC (type, 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;
+}
+
+/* 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. */
+
+/* ARGSUSED */
+static struct type *
+coff_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;
+ struct internal_syment sub_sym;
+ union internal_auxent sub_aux;
+ struct pending *osyms, *syms;
+ int o_nsyms;
+ register int n;
+ char *name;
+
+ type = coff_alloc_type (index);
+ if (within_function)
+ symlist = &local_symbols;
+ else
+ symlist = &file_symbols;
+ osyms = *symlist;
+ o_nsyms = osyms ? osyms->nsyms : 0;
+
+ while (!done && symnum < lastsym && symnum < nlist_nsyms_global)
+ {
+ read_one_sym (ms, &sub_sym, &sub_aux);
+ name = ms->c_name;
+ name = EXTERNAL_NAME (name, current_objfile->obfd);
+
+ switch (ms->c_sclass)
+ {
+ case C_MOE:
+ sym = (struct symbol *) xmalloc (sizeof (struct symbol));
+ memset (sym, 0, 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. */
+
+ if (length > 0)
+ TYPE_LENGTH (type) = length;
+ else
+ TYPE_LENGTH (type) = TARGET_INT_BIT / TARGET_CHAR_BIT; /* Assume ints */
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, 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 *xsym = syms->symbol[j];
+ SYMBOL_TYPE (xsym) = type;
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym);
+ TYPE_FIELD_VALUE (type, n) = 0;
+ TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym);
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+#if 0
+ /* This screws up perfectly good C programs with enums. FIXME. */
+ /* Is this Modula-2's BOOLEAN type? Flag it as such if so. */
+ if(TYPE_NFIELDS(type) == 2 &&
+ ((STREQ(TYPE_FIELD_NAME(type,0),"TRUE") &&
+ STREQ(TYPE_FIELD_NAME(type,1),"FALSE")) ||
+ (STREQ(TYPE_FIELD_NAME(type,1),"TRUE") &&
+ STREQ(TYPE_FIELD_NAME(type,0),"FALSE"))))
+ TYPE_CODE(type) = TYPE_CODE_BOOL;
+#endif
+ return type;
+}
+
+struct section_offsets *
+coff_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets) +
+ sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+/* Register our ability to parse symbols for coff BFD files */
+
+static struct sym_fns coff_sym_fns =
+{
+ "coff", /* sym_name: name or name prefix of BFD target type */
+ 4, /* sym_namelen: number of significant sym_name chars */
+ coff_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ coff_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ coff_symfile_read, /* sym_read: read a symbol file into symtab */
+ coff_symfile_finish, /* sym_finish: finished with file, cleanup */
+ coff_symfile_offsets, /* sym_offsets: xlate external to internal form */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_coffread ()
+{
+ add_symtab_fns(&coff_sym_fns);
+}
diff --git a/gnu/usr.bin/gdb/command.c b/gnu/usr.bin/gdb/gdb/command.c
index 79daea490383..abc2d84499c0 100644
--- a/gnu/usr.bin/gdb/command.c
+++ b/gnu/usr.bin/gdb/gdb/command.c
@@ -1,28 +1,53 @@
-/* Library for reading command lines and decoding commands.
- Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+/* Handle lists of commands, their decoding and documentation, for GDB.
+ Copyright 1986, 1989, 1990, 1991 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 free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+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 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"
#include "defs.h"
-#include <stdio.h>
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "value.h"
#include <ctype.h>
+#include <string.h>
-extern char *xmalloc ();
+/* Prototypes for local functions */
-/* Add element named NAME to command list *LIST.
+static void
+undef_cmd_error PARAMS ((char *, char *));
+
+static void
+show_user PARAMS ((char *, int));
+
+static void
+show_user_1 PARAMS ((struct cmd_list_element *, FILE *));
+
+static void
+make_command PARAMS ((char *, int));
+
+static void
+shell_escape PARAMS ((char *, int));
+
+static int
+parse_binary_operation PARAMS ((char *));
+
+static void
+print_doc_line PARAMS ((FILE *, char *));
+
+/* Add element named NAME.
+ CLASS is the top level category into which commands are broken down
+ for "help" purposes.
FUN should be the function to execute the command;
it will get a character string as argument, with leading
and trailing blanks already eliminated.
@@ -30,13 +55,15 @@ extern char *xmalloc ();
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. */
+ or with * for a command that most users don't need to know about.
+
+ Add this command to command list *LIST. */
struct cmd_list_element *
add_cmd (name, class, fun, doc, list)
char *name;
- int class;
- void (*fun) ();
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
char *doc;
struct cmd_list_element **list;
{
@@ -45,50 +72,52 @@ add_cmd (name, class, fun, doc, list)
delete_cmd (name, list);
c->next = *list;
- c->name = savestring (name, strlen (name));
+ c->name = name;
c->class = class;
- c->function = fun;
+ c->function.cfunc = fun;
c->doc = doc;
c->prefixlist = 0;
+ c->prefixname = (char *)NULL;
c->allow_unknown = 0;
+ c->hook = 0;
+ c->hookee = 0;
+ c->cmd_pointer = 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. */
+#if 0 /* Currently unused */
+
struct cmd_list_element *
add_abbrev_cmd (name, class, fun, doc, list)
char *name;
- int class;
- void (*fun) ();
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
char *doc;
struct cmd_list_element **list;
{
register struct cmd_list_element *c
- = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+ = add_cmd (name, class, fun, doc, list);
- delete_cmd (name, list);
- c->next = *list;
- c->name = savestring (name, strlen (name));
- c->class = class;
- c->function = fun;
- c->doc = doc;
- c->prefixlist = 0;
- c->allow_unknown = 0;
c->abbrev_flag = 1;
- c->aux = 0;
- *list = c;
return c;
}
+#endif
+
struct cmd_list_element *
add_alias_cmd (name, oldname, class, abbrev_flag, list)
char *name;
char *oldname;
- int class;
+ enum command_class class;
int abbrev_flag;
struct cmd_list_element **list;
{
@@ -98,7 +127,7 @@ add_alias_cmd (name, oldname, class, abbrev_flag, list)
register struct cmd_list_element *c;
copied_name = (char *) alloca (strlen (oldname) + 1);
strcpy (copied_name, oldname);
- old = lookup_cmd (&copied_name, *list, 0, 1, 1);
+ old = lookup_cmd (&copied_name, *list, "", 1, 1);
if (old == 0)
{
@@ -106,12 +135,12 @@ add_alias_cmd (name, oldname, class, abbrev_flag, list)
return 0;
}
- c = add_cmd (name, class, old->function, old->doc, list);
+ c = add_cmd (name, class, old->function.cfunc, 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;
+ c->cmd_pointer = old;
return c;
}
@@ -124,8 +153,8 @@ struct cmd_list_element *
add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
allow_unknown, list)
char *name;
- int class;
- void (*fun) ();
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
char *doc;
struct cmd_list_element **prefixlist;
char *prefixname;
@@ -139,14 +168,14 @@ add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
return c;
}
-/* Like add_prefix_cmd butsets the abbrev_flag on the new command. */
+/* Like add_prefix_cmd but sets the abbrev_flag on the new command. */
struct cmd_list_element *
add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
- allow_unknown, list)
+ allow_unknown, list)
char *name;
- int class;
- void (*fun) ();
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
char *doc;
struct cmd_list_element **prefixlist;
char *prefixname;
@@ -161,6 +190,70 @@ add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
return c;
}
+/* ARGSUSED */
+void
+not_just_help_class_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+}
+
+/* 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));
+
+ memcpy (showcmd, setcmd, 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, NULL);
+ 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
@@ -169,24 +262,33 @@ delete_cmd (name, list)
struct cmd_list_element **list;
{
register struct cmd_list_element *c;
+ struct cmd_list_element *p;
- while (*list && !strcmp ((*list)->name, name))
+ while (*list && STREQ ((*list)->name, name))
{
- *list = (*list)->next;
+ if ((*list)->hookee)
+ (*list)->hookee->hook = 0; /* Hook slips out of its mouth */
+ p = (*list)->next;
+ free ((PTR)*list);
+ *list = p;
}
if (*list)
for (c = *list; c->next;)
{
- if (!strcmp (c->next->name, name))
- c->next = c->next->next;
+ if (STREQ (c->next->name, name))
+ {
+ if (c->next->hookee)
+ c->next->hookee->hook = 0; /* hooked cmd gets away. */
+ p = c->next->next;
+ free ((PTR)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").
@@ -208,7 +310,7 @@ help_cmd (command, stream)
if (!command)
{
- help_list (cmdlist, "", -2, stream);
+ help_list (cmdlist, "", all_classes, stream);
return;
}
@@ -218,7 +320,7 @@ help_cmd (command, stream)
return;
/* There are three cases here.
- If c->prefixlist is nonzer, we have a prefix command.
+ 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.
@@ -226,23 +328,27 @@ help_cmd (command, stream)
If c->function is zero, we have a class name.
Print its documentation (as if it were a command)
- and then set class to he number of this class
+ 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)
+ if (c->prefixlist == 0 && c->function.cfunc != NULL)
return;
fprintf_filtered (stream, "\n");
/* If this is a prefix command, print it's subcommands */
if (c->prefixlist)
- help_list (*c->prefixlist, c->prefixname, -1, stream);
+ 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)
+ if (c->function.cfunc == NULL)
help_list (cmdlist, "", c->class, stream);
+
+ if (c->hook)
+ fprintf_filtered (stream, "\nThis command has a hook defined: %s\n",
+ c->hook->name);
}
/*
@@ -251,8 +357,8 @@ help_cmd (command, stream)
* 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, -1 for
- * everything, -2 for just classes, and non-negative for only things
+ * 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.
@@ -261,7 +367,7 @@ void
help_list (list, cmdtype, class, stream)
struct cmd_list_element *list;
char *cmdtype;
- int class;
+ enum command_class class;
FILE *stream;
{
int len;
@@ -282,14 +388,14 @@ help_list (list, cmdtype, class, stream)
strcpy (cmdtype2 + len - 1, " sub");
}
- if (class == -2)
+ 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, (class >= 0), stream);
+ help_cmd_list (list, class, cmdtype, (int)class >= 0, stream);
- if (class == -2)
+ 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);
@@ -300,6 +406,37 @@ 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 ((PTR)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.
@@ -310,52 +447,32 @@ Command name abbreviations are allowed if unambiguous.\n",
* CLASS should be:
* A non-negative class number to list only commands in that
* class.
- * -1 to list all commands in list.
- * -2 to list all classes in list.
+ * 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
+ * ones selected 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;
- int class;
+ enum command_class class;
char *prefix;
int recurse;
FILE *stream;
{
register struct cmd_list_element *c;
- register char *p;
- static char *line_buffer = 0;
- static int line_size;
-
- if (!line_buffer)
- {
- line_size = 80;
- line_buffer = (char *) xmalloc (line_size);
- }
for (c = list; c; c = c->next)
{
if (c->abbrev_flag == 0 &&
- (class == -1
- || (class == -2 && c->function == 0)
- || (class == c->class && c->function != 0)))
+ (class == all_commands
+ || (class == all_classes && c->function.cfunc == NULL)
+ || (class == c->class && c->function.cfunc != NULL)))
{
fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
- /* Print just the first line */
- p = c->doc;
- while (*p && *p != '\n') p++;
- if (p - c->doc > line_size - 1)
- {
- line_size = p - c->doc + 1;
- free (line_buffer);
- line_buffer = (char *) xmalloc (line_size);
- }
- strncpy (line_buffer, c->doc, p - c->doc);
- line_buffer[p - c->doc] = '\0';
- fputs_filtered (line_buffer, stream);
+ print_doc_line (stream, c->doc);
fputs_filtered ("\n", stream);
}
if (recurse
@@ -365,33 +482,41 @@ help_cmd_list (list, class, prefix, recurse, stream)
}
}
-/* 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).
+/* 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 point to the list in
+ which the last word was matched, and will return a pointer to the cmd
+ list element which the text matches. It will return NULL if no match at
+ all was possible. It will return -1 (cast appropriately, ick) if ambigous
+ matches are possible; in this case *RESULT_LIST will be set to point to
+ the list in which there are ambiguous choices (and *TEXT will be set to
+ the ambiguous text string).
+
+ If the located command was an abbreviation, this routine returns the base
+ command of the abbreviation.
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.
+ 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 NULL
+ 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. In the case of an ambiguous
+ return *TEXT is advanced past the last non-ambiguous prefix (e.g.
+ "info t" can be "info types" or "info target"; upon return *TEXT has been
+ advanced past "info ").
+
+ 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 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). */
+ 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 NULL). */
struct cmd_list_element *
lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
@@ -428,7 +553,7 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
for (tmp = 0; tmp < len; tmp++)
{
char x = (*text)[tmp];
- command[tmp] = (x >= 'A' && x <= 'Z') ? x - 'A' + 'a' : x;
+ command[tmp] = isupper(x) ? tolower(x) : x;
}
command[len] = '\0';
@@ -437,7 +562,7 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
nfound = 0;
for (c = clist; c; c = c->next)
if (!strncmp (command, c->name, len)
- && (!ignore_help_classes || c->function))
+ && (!ignore_help_classes || c->function.cfunc))
{
found = c;
nfound++;
@@ -454,15 +579,24 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
if (nfound > 1)
{
- *result_list = 0; /* Will be modified in calling routine
- if we know what the prefix command is.
- */
+ 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 this was an abbreviation, use the base command instead. */
+
+ if (found->cmd_pointer)
+ found = found->cmd_pointer;
+
+ /* If we found a prefix command, keep looking. */
+
if (found->prefixlist)
{
c = lookup_cmd_1 (text, *found->prefixlist, result_list,
@@ -470,7 +604,8 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
if (!c)
{
/* Didn't find anything; this is as far as we got. */
- *result_list = clist;
+ if (result_list != NULL)
+ *result_list = clist;
return found;
}
else if (c == (struct cmd_list_element *) -1)
@@ -478,12 +613,13 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
/* 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)
- /* 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;
+ 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
@@ -494,11 +630,26 @@ lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
}
else
{
- *result_list = clist;
+ if (result_list != NULL)
+ *result_list = clist;
return found;
}
}
+/* All this hair to move the space to the front of cmdtype */
+
+static void
+undef_cmd_error (cmdtype, q)
+ char *cmdtype, *q;
+{
+ error ("Undefined %scommand: \"%s\". Try \"help%s%.*s\".",
+ cmdtype,
+ q,
+ *cmdtype? " ": "",
+ strlen(cmdtype)-1,
+ cmdtype);
+}
+
/* 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
@@ -547,8 +698,7 @@ lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
q = (char *) alloca (p - *line + 1);
strncpy (q, *line, p - *line);
q[p-*line] = '\0';
-
- error ("Undefined %scommand: \"%s\".", cmdtype, q);
+ undef_cmd_error (cmdtype, q);
}
}
else
@@ -587,7 +737,7 @@ lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
for (c = local_list; c; c = c->next)
if (!strncmp (*line, c->name, amb_len))
{
- if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
+ if (strlen (ambbuf) + strlen (c->name) + 6 < (int)sizeof ambbuf)
{
if (strlen (ambbuf))
strcat (ambbuf, ", ");
@@ -601,6 +751,7 @@ lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
}
error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype,
*line, ambbuf);
+ return 0; /* lint */
}
}
else
@@ -611,11 +762,12 @@ lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
(*line)++;
if (c->prefixlist && **line && !c->allow_unknown)
- error ("Undefined %scommand: \"%s\".", c->prefixname, *line);
+ undef_cmd_error (c->prefixname, *line);
/* Seems to be what he wants. Return it. */
return c;
}
+ return 0;
}
#if 0
@@ -658,10 +810,7 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
/* Find end of command name. */
p = *line;
- while (*p == '-'
- || (*p >= 'a' && *p <= 'z')
- || (*p >= 'A' && *p <= 'Z')
- || (*p >= '0' && *p <= '9'))
+ while (*p == '-' || isalnum(*p))
p++;
/* Look up the command name.
@@ -686,8 +835,8 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
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';
+ if (isupper(x))
+ processed_cmd[cmd_len] = tolower(x);
else
processed_cmd[cmd_len] = x;
}
@@ -760,12 +909,18 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
/* Return a vector of char pointers which point to the different
- possible completions in LIST of TEXT. */
+ possible completions in LIST of TEXT.
+
+ WORD points in the same buffer as TEXT, and completions should be
+ returned relative to this position. For example, suppose TEXT is "foo"
+ and we want to complete to "foobar". If WORD is "oo", return
+ "oobar"; if WORD is "baz/foo", return "baz/foobar". */
char **
-complete_on_cmdlist (list, text)
+complete_on_cmdlist (list, text, word)
struct cmd_list_element *list;
char *text;
+ char *word;
{
struct cmd_list_element *ptr;
char **matchlist;
@@ -780,30 +935,44 @@ complete_on_cmdlist (list, text)
for (ptr = list; ptr; ptr = ptr->next)
if (!strncmp (ptr->name, text, textlen)
&& !ptr->abbrev_flag
- && (ptr->function
+ && (ptr->function.cfunc
|| ptr->prefixlist))
{
if (matches == sizeof_matchlist)
{
sizeof_matchlist *= 2;
- matchlist = (char **) xrealloc (matchlist,
+ matchlist = (char **) xrealloc ((char *)matchlist,
(sizeof_matchlist
* sizeof (char *)));
}
matchlist[matches] = (char *)
- xmalloc (strlen (ptr->name) + 1);
- strcpy (matchlist[matches++], ptr->name);
+ xmalloc (strlen (word) + strlen (ptr->name) + 1);
+ if (word == text)
+ strcpy (matchlist[matches], ptr->name);
+ else if (word > text)
+ {
+ /* Return some portion of ptr->name. */
+ strcpy (matchlist[matches], ptr->name + (word - text));
+ }
+ else
+ {
+ /* Return some of text plus ptr->name. */
+ strncpy (matchlist[matches], word, text - word);
+ matchlist[matches][text - word] = '\0';
+ strcat (matchlist[matches], ptr->name);
+ }
+ ++matches;
}
if (matches == 0)
{
- free (matchlist);
+ free ((PTR)matchlist);
matchlist = 0;
}
else
{
- matchlist = (char **) xrealloc (matchlist, ((matches + 1)
+ matchlist = (char **) xrealloc ((char *)matchlist, ((matches + 1)
* sizeof (char *)));
matchlist[matches] = (char *) 0;
}
@@ -811,20 +980,231 @@ complete_on_cmdlist (list, text)
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++) != '\000')
+ {
+ 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.");
+ *(unsigned int *) c->var = parse_and_eval_address (arg);
+ if (*(unsigned int *) c->var == 0)
+ *(unsigned int *) c->var = UINT_MAX;
+ break;
+ case var_integer:
+ {
+ unsigned int val;
+ if (arg == NULL)
+ error_no_arg ("integer to set it to.");
+ val = parse_and_eval_address (arg);
+ if (val == 0)
+ *(int *) c->var = INT_MAX;
+ else if (val >= INT_MAX)
+ error ("integer %u out of range", val);
+ else
+ *(int *) c->var = val;
+ 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++)
+ gdb_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, "%u", *(unsigned int *) c->var);
+ break;
+ case var_integer:
+ if (*(int *) c->var == INT_MAX)
+ {
+ fputs_filtered ("unlimited", stdout);
+ }
+ else
+ fprintf_filtered (stdout, "%d", *(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.sfunc) (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);
+ }
+ }
+}
+
+/* ARGSUSED */
static void
shell_escape (arg, from_tty)
char *arg;
int from_tty;
{
+#ifdef CANT_FORK
+ /* FIXME: what about errors (I don't know how GO32 system() handles
+ them)? */
+ system (arg);
+#else /* Can fork. */
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)
+ if ((p = strrchr (user_shell, '/')) == NULL)
p = user_shell;
else
p++; /* Get past '/' */
@@ -845,6 +1225,74 @@ shell_escape (arg, from_tty)
;
else
error ("Fork failed");
+#endif /* Can fork. */
+}
+
+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);
+}
+
+static void
+show_user_1 (c, stream)
+ struct cmd_list_element *c;
+ FILE *stream;
+{
+ register struct command_line *cmdlines;
+
+ cmdlines = c->user_commands;
+ if (!cmdlines)
+ return;
+ fputs_filtered ("User command ", stream);
+ fputs_filtered (c->name, stream);
+ fputs_filtered (":\n", stream);
+ while (cmdlines)
+ {
+ fputs_filtered (cmdlines->line, stream);
+ fputs_filtered ("\n", stream);
+ cmdlines = cmdlines->next;
+ }
+ fputs_filtered ("\n", stream);
+}
+
+/* ARGSUSED */
+static void
+show_user (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct cmd_list_element *c;
+ extern struct cmd_list_element *cmdlist;
+
+ if (args)
+ {
+ c = lookup_cmd (&args, cmdlist, "", 0, 1);
+ if (c->class != class_user)
+ error ("Not a user command.");
+ show_user_1 (c, stdout);
+ }
+ else
+ {
+ for (c = cmdlist; c; c = c->next)
+ {
+ if (c->class == class_user)
+ show_user_1 (c, stdout);
+ }
+ }
}
void
@@ -853,4 +1301,10 @@ _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.");
+ add_cmd ("user", no_class, show_user,
+ "Show definitions of user defined commands.\n\
+Argument is the name of the user defined command.\n\
+With no argument, show definitions of all user defined commands.", &showlist);
}
diff --git a/gnu/usr.bin/gdb/gdb/command.h b/gnu/usr.bin/gdb/gdb/command.h
new file mode 100644
index 000000000000..ee587c30659d
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/command.h
@@ -0,0 +1,241 @@
+/* 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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (COMMAND_H)
+#define COMMAND_H 1
+
+/* 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,
+
+ /* Like var_uinteger but signed. *VAR is an int. The user can type 0
+ to mean "unlimited", which is stored in *VAR as INT_MAX. */
+ var_integer,
+
+ /* 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. */
+ union {
+ void (*cfunc) PARAMS ((char *args, int from_tty));
+ void (*sfunc) PARAMS ((char *args, int from_tty,
+ struct cmd_list_element *c));
+ } function;
+# define NO_FUNCTION ((void (*) PARAMS((char *args, int from_tty))) 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;
+
+ /* Hook for another command to be executed before this command. */
+ struct cmd_list_element *hook;
+
+ /* 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. TEXT is the text beyond
+ what was matched for the command itself (leading whitespace is
+ skipped). It stops where we are supposed to stop completing
+ (rl_point) and is '\0' terminated.
+
+ Return value is a malloc'd vector of pointers to possible completions
+ terminated with NULL. If there are no completions, returning a pointer
+ to a NULL would work but returning NULL itself is also valid.
+ WORD points in the same buffer as TEXT, and completions should be
+ returned relative to this position. For example, suppose TEXT is "foo"
+ and we want to complete to "foobar". If WORD is "oo", return
+ "oobar"; if WORD is "baz/foo", return "baz/foobar". */
+ char ** (*completer) PARAMS ((char *text, char *word));
+
+ /* 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;
+
+ /* Pointer to command that is hooked by this one,
+ so the hook can be removed when this one is deleted. */
+ struct cmd_list_element *hookee;
+
+ /* Pointer to command that is aliased by this one, so the
+ aliased command can be located in case it has been hooked. */
+ struct cmd_list_element *cmd_pointer;
+ };
+
+/* Forward-declarations of the entry-points of command.c. */
+
+extern struct cmd_list_element *
+add_cmd PARAMS ((char *, enum command_class, void (*fun) (char *, int),
+ char *, struct cmd_list_element **));
+
+extern struct cmd_list_element *
+add_alias_cmd PARAMS ((char *, char *, enum command_class, int,
+ struct cmd_list_element **));
+
+extern struct cmd_list_element *
+add_prefix_cmd PARAMS ((char *, enum command_class, void (*fun) (char *, int),
+ char *, struct cmd_list_element **, char *, int,
+ struct cmd_list_element **));
+
+extern struct cmd_list_element *
+add_abbrev_prefix_cmd PARAMS ((char *, enum command_class,
+ void (*fun) (char *, int), char *,
+ struct cmd_list_element **, char *, int,
+ struct cmd_list_element **));
+
+extern struct cmd_list_element *
+lookup_cmd PARAMS ((char **, struct cmd_list_element *, char *, int, int));
+
+extern struct cmd_list_element *
+lookup_cmd_1 PARAMS ((char **, struct cmd_list_element *,
+ struct cmd_list_element **, int));
+
+extern void
+add_com PARAMS ((char *, enum command_class, void (*fun)(char *, int),
+ char *));
+
+extern void
+add_com_alias PARAMS ((char *, char *, enum command_class, int));
+
+extern void
+add_info PARAMS ((char *, void (*fun) (char *, int), char *));
+
+extern void
+add_info_alias PARAMS ((char *, char *, int));
+
+extern char **complete_on_cmdlist PARAMS ((struct cmd_list_element *,
+ char *, char *));
+
+extern void
+delete_cmd PARAMS ((char *, struct cmd_list_element **));
+
+extern void
+help_cmd PARAMS ((char *, FILE *));
+
+extern void
+help_list PARAMS ((struct cmd_list_element *, char *, enum command_class,
+ FILE *));
+
+extern void
+help_cmd_list PARAMS ((struct cmd_list_element *, enum command_class, char *,
+ int, FILE *));
+
+extern struct cmd_list_element *
+add_set_cmd PARAMS ((char *, enum command_class, var_types, char *, char *,
+ struct cmd_list_element **));
+
+extern struct cmd_list_element *
+add_show_from_set PARAMS ((struct cmd_list_element *,
+ struct cmd_list_element **));
+
+/* 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 PARAMS ((char *, int, struct cmd_list_element *));
+
+/* Do a "show" command for each thing on a command list. */
+
+extern void
+cmd_show_list PARAMS ((struct cmd_list_element *, int, char *));
+
+extern void
+error_no_arg PARAMS ((char *));
+
+extern void
+dont_repeat PARAMS ((void));
+
+/* Used to mark commands that don't do anything. If we just leave the
+ function field NULL, the command is interpreted as a help topic, or
+ as a class of commands. */
+
+extern void
+not_just_help_class_command PARAMS ((char *, int));
+
+#endif /* !defined (COMMAND_H) */
diff --git a/gnu/usr.bin/gdb/gdb/complaints.c b/gnu/usr.bin/gdb/gdb/complaints.c
new file mode 100644
index 000000000000..079ca5adc643
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/complaints.c
@@ -0,0 +1,158 @@
+/* Support for complaint handling during symbol reading in GDB.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "complaints.h"
+#include "gdbcmd.h"
+#include <varargs.h>
+
+/* Structure to manage complaints about symbol file contents. */
+
+struct complaint complaint_root[1] = {
+ {
+ (char *) NULL, /* Complaint message */
+ 0, /* Complaint counter */
+ complaint_root /* Next complaint. */
+ }
+};
+
+/* How many complaints about a particular thing should be printed before
+ we stop whining about it? Default is no whining at all, since so many
+ systems have ill-constructed symbol files. */
+
+static unsigned int stop_whining = 0;
+
+/* Should each complaint be self explanatory, or should we assume that
+ a series of complaints is being produced?
+ case 0: self explanatory message.
+ case 1: First message of a series that must start off with explanation.
+ case 2: Subsequent message, when user already knows we are reading
+ symbols and we can just state our piece. */
+
+static int complaint_series = 0;
+
+/* External variables and functions referenced. */
+
+extern int info_verbose;
+
+
+/* Functions to handle complaints during symbol reading. */
+
+/* Print a complaint about the input symbols, and link the complaint block
+ into a chain for later handling. */
+
+/* VARARGS */
+void
+complain (va_alist)
+ va_dcl
+{
+ va_list args;
+ struct complaint *complaint;
+
+ va_start (args);
+ complaint = va_arg (args, struct complaint *);
+ complaint -> counter++;
+ if (complaint -> next == NULL)
+ {
+ complaint -> next = complaint_root -> next;
+ complaint_root -> next = complaint;
+ }
+ if (complaint -> counter > stop_whining)
+ {
+ return;
+ }
+ wrap_here ("");
+
+ switch (complaint_series + (info_verbose << 1))
+ {
+
+ /* Isolated messages, must be self-explanatory. */
+ case 0:
+ begin_line ();
+ puts_filtered ("During symbol reading, ");
+ wrap_here ("");
+ vprintf_filtered (complaint -> message, args);
+ puts_filtered (".\n");
+ break;
+
+ /* First of a series, without `set verbose'. */
+ case 1:
+ begin_line ();
+ puts_filtered ("During symbol reading...");
+ vprintf_filtered (complaint -> message, args);
+ puts_filtered ("...");
+ wrap_here ("");
+ complaint_series++;
+ break;
+
+ /* Subsequent messages of a series, or messages under `set verbose'.
+ (We'll already have produced a "Reading in symbols for XXX..."
+ message and will clean up at the end with a newline.) */
+ default:
+ vprintf_filtered (complaint -> message, args);
+ puts_filtered ("...");
+ wrap_here ("");
+ }
+ /* If GDB dumps core, we'd like to see the complaints first. Presumably
+ GDB will not be sending so many complaints that this becomes a
+ performance hog. */
+ fflush (stdout);
+ va_end (args);
+}
+
+/* Clear out all complaint counters that have ever been incremented.
+ If sym_reading is 1, be less verbose about successive complaints,
+ since the messages are appearing all together during a command that
+ reads symbols (rather than scattered around as psymtabs get fleshed
+ out into symtabs at random times). If noisy is 1, we are in a
+ noisy symbol reading command, and our caller will print enough
+ context for the user to figure it out. */
+
+void
+clear_complaints (sym_reading, noisy)
+ int sym_reading;
+ int noisy;
+{
+ struct complaint *p;
+
+ for (p = complaint_root -> next; p != complaint_root; p = p -> next)
+ {
+ p -> counter = 0;
+ }
+
+ if (!sym_reading && !noisy && complaint_series > 1)
+ {
+ /* Terminate previous series, since caller won't. */
+ puts_filtered ("\n");
+ }
+
+ complaint_series = sym_reading ? 1 + noisy : 0;
+}
+
+void
+_initialize_complaints ()
+{
+ add_show_from_set
+ (add_set_cmd ("complaints", class_support, var_zinteger,
+ (char *) &stop_whining,
+ "Set max number of complaints about incorrect symbols.",
+ &setlist),
+ &showlist);
+
+}
diff --git a/gnu/usr.bin/gdb/gdb/complaints.h b/gnu/usr.bin/gdb/gdb/complaints.h
new file mode 100644
index 000000000000..f7ff5a568142
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/complaints.h
@@ -0,0 +1,46 @@
+/* Definitions for complaint handling during symbol reading in GDB.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* 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 complaints.c) */
+
+extern void
+complain ();
+
+extern void
+clear_complaints PARAMS ((int, int));
diff --git a/gnu/usr.bin/gdb/gdb/copying.c b/gnu/usr.bin/gdb/gdb/copying.c
new file mode 100644
index 000000000000..ffc884a67140
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/copying.c
@@ -0,0 +1,327 @@
+/* ==> Do not modify this file!! It is created automatically
+ by copying.awk. Modify copying.awk instead. <== */
+
+#include "defs.h"
+#include "command.h"
+#include "gdbcmd.h"
+
+static void
+show_copying_command PARAMS ((char *, int));
+
+static void
+show_warranty_command PARAMS ((char *, int));
+
+extern int immediate_quit;
+static void
+show_copying_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ immediate_quit++;
+ printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
+ printf_filtered (" Version 2, June 1991\n");
+ printf_filtered ("\n");
+ printf_filtered (" Copyright (C) 1989, 1991 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 licenses for most software are designed to take away your\n");
+ printf_filtered ("freedom to share and change it. By contrast, the GNU 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. This\n");
+ printf_filtered ("General Public License applies to most of the Free Software\n");
+ printf_filtered ("Foundation's software and to any other program whose authors commit to\n");
+ printf_filtered ("using it. (Some other Free Software Foundation software is covered by\n");
+ printf_filtered ("the GNU Library General Public License instead.) You can apply it to\n");
+ printf_filtered ("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. Our General Public Licenses are designed to make sure that you\n");
+ printf_filtered ("have the freedom to distribute copies of free software (and charge for\n");
+ printf_filtered ("this service if you wish), that you receive source code or can get it\n");
+ printf_filtered ("if you want it, that you can change the software or use pieces of it\n");
+ printf_filtered ("in new free 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 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 show them these terms so they know their\n");
+ printf_filtered ("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 (" Finally, any free program is threatened constantly by software\n");
+ printf_filtered ("patents. We wish to avoid the danger that redistributors of a free\n");
+ printf_filtered ("program will individually obtain patent licenses, in effect making the\n");
+ printf_filtered ("program proprietary. To prevent this, we have made it clear that any\n");
+ printf_filtered ("patent must be licensed for everyone's free use or not licensed at all.\n");
+ printf_filtered ("\n");
+ printf_filtered (" The precise terms and conditions for copying, distribution and\n");
+ printf_filtered ("modification follow.\n");
+ printf_filtered ("\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 applies to any program or other work which contains\n");
+ printf_filtered ("a notice placed by the copyright holder saying it may be distributed\n");
+ printf_filtered ("under the terms of this General Public License. The \"Program\", below,\n");
+ printf_filtered ("refers to any such program or work, and a \"work based on the Program\"\n");
+ printf_filtered ("means either the Program or any derivative work under copyright law:\n");
+ printf_filtered ("that is to say, a work containing the Program or a portion of it,\n");
+ printf_filtered ("either verbatim or with modifications and/or translated into another\n");
+ printf_filtered ("language. (Hereinafter, translation is included without limitation in\n");
+ printf_filtered ("the term \"modification\".) Each licensee is addressed as \"you\".\n");
+ printf_filtered ("\n");
+ printf_filtered ("Activities other than copying, distribution and modification are not\n");
+ printf_filtered ("covered by this License; they are outside its scope. The act of\n");
+ printf_filtered ("running the Program is not restricted, and the output from the Program\n");
+ printf_filtered ("is covered only if its contents constitute a work based on the\n");
+ printf_filtered ("Program (independent of having been made by running the Program).\n");
+ printf_filtered ("Whether that is true depends on what the Program does.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 1. You may copy and distribute verbatim copies of the Program's\n");
+ printf_filtered ("source code as you receive it, in any medium, provided that you\n");
+ printf_filtered ("conspicuously and appropriately publish on each copy an appropriate\n");
+ printf_filtered ("copyright notice and disclaimer of warranty; keep intact all the\n");
+ printf_filtered ("notices that refer to this License and to the absence of any warranty;\n");
+ printf_filtered ("and give any other recipients of the Program a copy of this License\n");
+ printf_filtered ("along with the Program.\n");
+ printf_filtered ("\n");
+ printf_filtered ("You may charge a fee for the physical act of transferring a copy, and\n");
+ printf_filtered ("you may at your option offer warranty protection in exchange for a fee.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 2. You may modify your copy or copies of the Program or any portion\n");
+ printf_filtered ("of it, thus forming a work based on the Program, and copy and\n");
+ printf_filtered ("distribute such modifications or work under the terms of Section 1\n");
+ printf_filtered ("above, provided that you also meet all of these conditions:\n");
+ printf_filtered ("\n");
+ printf_filtered (" a) You must cause the modified files to carry prominent notices\n");
+ printf_filtered (" stating that you changed the files and the date of any change.\n");
+ printf_filtered ("\n");
+ printf_filtered (" b) You must cause any work that you distribute or publish, that in\n");
+ printf_filtered (" whole or in part contains or is derived from the Program or any\n");
+ printf_filtered (" part thereof, to be licensed as a whole at no charge to all third\n");
+ printf_filtered (" parties under the terms of this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" c) If the modified program normally reads commands interactively\n");
+ printf_filtered (" when run, you must cause it, when started running for such\n");
+ printf_filtered (" interactive use in the most ordinary way, to print or display an\n");
+ printf_filtered (" announcement including an appropriate copyright notice and a\n");
+ printf_filtered (" notice that there is no warranty (or else, saying that you provide\n");
+ printf_filtered (" a warranty) and that users may redistribute the program under\n");
+ printf_filtered (" these conditions, and telling the user how to view a copy of this\n");
+ printf_filtered (" License. (Exception: if the Program itself is interactive but\n");
+ printf_filtered (" does not normally print such an announcement, your work based on\n");
+ printf_filtered (" the Program is not required to print an announcement.)\n");
+ printf_filtered ("\n");
+ printf_filtered ("These requirements apply to the modified work as a whole. If\n");
+ printf_filtered ("identifiable sections of that work are not derived from the Program,\n");
+ printf_filtered ("and can be reasonably considered independent and separate works in\n");
+ printf_filtered ("themselves, then this License, and its terms, do not apply to those\n");
+ printf_filtered ("sections when you distribute them as separate works. But when you\n");
+ printf_filtered ("distribute the same sections as part of a whole which is a work based\n");
+ printf_filtered ("on the Program, the distribution of the whole must be on the terms of\n");
+ printf_filtered ("this License, whose permissions for other licensees extend to the\n");
+ printf_filtered ("entire whole, and thus to each and every part regardless of who wrote it.\n");
+ printf_filtered ("\n");
+ printf_filtered ("Thus, it is not the intent of this section to claim rights or contest\n");
+ printf_filtered ("your rights to work written entirely by you; rather, the intent is to\n");
+ printf_filtered ("exercise the right to control the distribution of derivative or\n");
+ printf_filtered ("collective works based on the Program.\n");
+ printf_filtered ("\n");
+ printf_filtered ("In addition, mere aggregation of another work not based on the Program\n");
+ printf_filtered ("with the Program (or with a work based on the Program) on a volume of\n");
+ printf_filtered ("a storage or distribution medium does not bring the other work under\n");
+ printf_filtered ("the scope of this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 3. You may copy and distribute the Program (or a work based on it,\n");
+ printf_filtered ("under Section 2) in object code or executable form under the terms of\n");
+ printf_filtered ("Sections 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 Sections\n");
+ printf_filtered (" 1 and 2 above on a medium customarily used for software interchange; 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, for a charge no more than your\n");
+ printf_filtered (" cost of physically performing source distribution, a complete\n");
+ printf_filtered (" machine-readable copy of the corresponding source code, to be\n");
+ printf_filtered (" distributed under the terms of Sections 1 and 2 above on a medium\n");
+ printf_filtered (" customarily used for software interchange; or,\n");
+ printf_filtered ("\n");
+ printf_filtered (" c) Accompany it with the information you received as to the offer\n");
+ printf_filtered (" to distribute corresponding source code. (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 with such\n");
+ printf_filtered (" an offer, in accord with Subsection b above.)\n");
+ printf_filtered ("\n");
+ printf_filtered ("The source code for a work means the preferred form of the work for\n");
+ printf_filtered ("making modifications to it. For an executable work, complete source\n");
+ printf_filtered ("code means all the source code for all modules it contains, plus any\n");
+ printf_filtered ("associated interface definition files, plus the scripts used to\n");
+ printf_filtered ("control compilation and installation of the executable. However, as a\n");
+ printf_filtered ("special exception, the source code distributed need not include\n");
+ printf_filtered ("anything that is normally distributed (in either source or binary\n");
+ printf_filtered ("form) with the major components (compiler, kernel, and so on) of the\n");
+ printf_filtered ("operating system on which the executable runs, unless that component\n");
+ printf_filtered ("itself accompanies the executable.\n");
+ printf_filtered ("\n");
+ printf_filtered ("If distribution of executable or object code is made by offering\n");
+ printf_filtered ("access to copy from a designated place, then offering equivalent\n");
+ printf_filtered ("access to copy the source code from the same place counts as\n");
+ printf_filtered ("distribution of the source code, even though third parties are not\n");
+ printf_filtered ("compelled to copy the source along with the object code.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 4. You may not copy, modify, sublicense, or distribute the Program\n");
+ printf_filtered ("except as expressly provided under this License. Any attempt\n");
+ printf_filtered ("otherwise to copy, modify, sublicense or distribute the Program is\n");
+ printf_filtered ("void, and will automatically terminate your rights under this License.\n");
+ printf_filtered ("However, parties who have received copies, or rights, from you under\n");
+ printf_filtered ("this License will not have their licenses terminated so long as such\n");
+ printf_filtered ("parties remain in full compliance.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 5. You are not required to accept this License, since you have not\n");
+ printf_filtered ("signed it. However, nothing else grants you permission to modify or\n");
+ printf_filtered ("distribute the Program or its derivative works. These actions are\n");
+ printf_filtered ("prohibited by law if you do not accept this License. Therefore, by\n");
+ printf_filtered ("modifying or distributing the Program (or any work based on the\n");
+ printf_filtered ("Program), you indicate your acceptance of this License to do so, and\n");
+ printf_filtered ("all its terms and conditions for copying, distributing or modifying\n");
+ printf_filtered ("the Program or works based on it.\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\n");
+ printf_filtered ("original licensor to copy, distribute or modify the Program subject to\n");
+ printf_filtered ("these terms and conditions. You may not impose any further\n");
+ printf_filtered ("restrictions on the recipients' exercise of the rights granted herein.\n");
+ printf_filtered ("You are not responsible for enforcing compliance by third parties to\n");
+ printf_filtered ("this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 7. If, as a consequence of a court judgment or allegation of patent\n");
+ printf_filtered ("infringement or for any other reason (not limited to patent issues),\n");
+ printf_filtered ("conditions are imposed on you (whether by court order, agreement or\n");
+ printf_filtered ("otherwise) that contradict the conditions of this License, they do not\n");
+ printf_filtered ("excuse you from the conditions of this License. If you cannot\n");
+ printf_filtered ("distribute so as to satisfy simultaneously your obligations under this\n");
+ printf_filtered ("License and any other pertinent obligations, then as a consequence you\n");
+ printf_filtered ("may not distribute the Program at all. For example, if a patent\n");
+ printf_filtered ("license would not permit royalty-free redistribution of the Program by\n");
+ printf_filtered ("all those who receive copies directly or indirectly through you, then\n");
+ printf_filtered ("the only way you could satisfy both it and this License would be to\n");
+ printf_filtered ("refrain entirely from distribution of the Program.\n");
+ printf_filtered ("\n");
+ printf_filtered ("If any portion of this section is held invalid or unenforceable under\n");
+ printf_filtered ("any particular circumstance, the balance of the section is intended to\n");
+ printf_filtered ("apply and the section as a whole is intended to apply in other\n");
+ printf_filtered ("circumstances.\n");
+ printf_filtered ("\n");
+ printf_filtered ("It is not the purpose of this section to induce you to infringe any\n");
+ printf_filtered ("patents or other property right claims or to contest validity of any\n");
+ printf_filtered ("such claims; this section has the sole purpose of protecting the\n");
+ printf_filtered ("integrity of the free software distribution system, which is\n");
+ printf_filtered ("implemented by public license practices. Many people have made\n");
+ printf_filtered ("generous contributions to the wide range of software distributed\n");
+ printf_filtered ("through that system in reliance on consistent application of that\n");
+ printf_filtered ("system; it is up to the author/donor to decide if he or she is willing\n");
+ printf_filtered ("to distribute software through any other system and a licensee cannot\n");
+ printf_filtered ("impose that choice.\n");
+ printf_filtered ("\n");
+ printf_filtered ("This section is intended to make thoroughly clear what is believed to\n");
+ printf_filtered ("be a consequence of the rest of this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 8. If the distribution and/or use of the Program is restricted in\n");
+ printf_filtered ("certain countries either by patents or by copyrighted interfaces, the\n");
+ printf_filtered ("original copyright holder who places the Program under this License\n");
+ printf_filtered ("may add an explicit geographical distribution limitation excluding\n");
+ printf_filtered ("those countries, so that distribution is permitted only in or among\n");
+ printf_filtered ("countries not thus excluded. In such case, this License incorporates\n");
+ printf_filtered ("the limitation as if written in the body of this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 9. 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 this 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 ("this License, you may choose any version ever published by the Free Software\n");
+ printf_filtered ("Foundation.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 10. 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
+show_warranty_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ immediate_quit++;
+ printf_filtered (" NO WARRANTY\n");
+ printf_filtered ("\n");
+ printf_filtered (" 11. 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 (" 12. 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_cmd ("copying", no_class, show_copying_command,
+ "Conditions for redistributing copies of GDB.",
+ &showlist);
+ add_cmd ("warranty", no_class, show_warranty_command,
+ "Various kinds of warranty you do not have.",
+ &showlist);
+
+ /* For old-timers, allow "info copying", etc. */
+ add_info ("copying", show_copying_command,
+ "Conditions for redistributing copies of GDB.");
+ add_info ("warranty", show_warranty_command,
+ "Various kinds of warranty you do not have.");
+}
diff --git a/gnu/usr.bin/gdb/gdb/core.c b/gnu/usr.bin/gdb/gdb/core.c
new file mode 100644
index 000000000000..36c9ab5e75a0
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/core.c
@@ -0,0 +1,291 @@
+/* Core dump and executable file functions above target vector, for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "dis-asm.h"
+
+extern char registers[];
+
+/* Hook for `exec_file_command' command to call. */
+
+void (*exec_file_display_hook) PARAMS ((char *)) = NULL;
+
+/* Binary file diddling handle for the core file. */
+
+bfd *core_bfd = NULL;
+
+
+/* Backward compatability with old way of specifying core files. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ struct target_ops *t;
+
+ dont_repeat (); /* Either way, seems bogus. */
+
+ t = find_core_target ();
+ if (t != NULL)
+ if (!filename)
+ (t->to_detach) (filename, from_tty);
+ else
+ (t->to_open) (filename, from_tty);
+ else
+ error ("GDB can't read core files on this machine.");
+}
+
+
+/* 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) PARAMS ((char *));
+{
+ 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
+}
+
+/* If we have both a core file and an exec file,
+ print a warning if they don't go together. */
+
+void
+validate_files ()
+{
+ if (exec_bfd && core_bfd)
+ {
+ if (!core_file_matches_executable_p (core_bfd, exec_bfd))
+ warning ("core file may not match specified executable file.");
+ else if (bfd_get_mtime(exec_bfd) > bfd_get_mtime(core_bfd))
+ warning ("exec file is newer than core file.");
+ }
+}
+
+/* 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;
+}
+
+
+/* Report a memory error with error(). */
+
+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 at address %s.",
+ local_hex_string((unsigned long) memaddr));
+ }
+ else
+ {
+ error ("Error accessing memory address %s: %s.",
+ local_hex_string ((unsigned long) memaddr),
+ safe_strerror (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);
+}
+
+/* Like target_read_memory, but slightly different parameters. */
+
+int
+dis_asm_read_memory (memaddr, myaddr, len, info)
+ bfd_vma memaddr;
+ bfd_byte *myaddr;
+ int len;
+ disassemble_info *info;
+{
+ return target_read_memory (memaddr, (char *) myaddr, len);
+}
+
+/* Like memory_error with slightly different parameters. */
+void
+dis_asm_memory_error (status, memaddr, info)
+ int status;
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ memory_error (status, memaddr);
+}
+
+/* Like print_address with slightly different parameters. */
+void
+dis_asm_print_address (addr, info)
+ bfd_vma addr;
+ struct disassemble_info *info;
+{
+ print_address (addr, info->stream);
+}
+
+/* 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. */
+
+LONGEST
+read_memory_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ char buf[sizeof (LONGEST)];
+
+ read_memory (memaddr, buf, len);
+ return extract_signed_integer (buf, len);
+}
+
+unsigned LONGEST
+read_memory_unsigned_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ char buf[sizeof (unsigned LONGEST)];
+
+ read_memory (memaddr, buf, len);
+ return extract_unsigned_integer (buf, len);
+}
+
+/* The current default bfd target. Points to storage allocated for
+ gnutarget_string. */
+char *gnutarget;
+
+/* Same thing, except it is "auto" not NULL for the default case. */
+static char *gnutarget_string;
+
+static void set_gnutarget_command
+ PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+set_gnutarget_command (ignore, from_tty, c)
+ char *ignore;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (STREQ (gnutarget_string, "auto"))
+ gnutarget = NULL;
+ else
+ gnutarget = gnutarget_string;
+}
+
+/* Set the gnutarget. */
+void
+set_gnutarget (newtarget)
+ char *newtarget;
+{
+ if (gnutarget_string != NULL)
+ free (gnutarget_string);
+ gnutarget_string = savestring (newtarget, strlen (newtarget));
+ set_gnutarget_command (NULL, 0, NULL);
+}
+
+void
+_initialize_core()
+{
+ struct cmd_list_element *c;
+ c = add_cmd ("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.", &cmdlist);
+ c->completer = filename_completer;
+
+ c = add_set_cmd ("gnutarget", class_files, var_string_noescape,
+ (char *) &gnutarget_string,
+ "Set the current BFD target.\n\
+Use `set gnutarget auto' to specify automatic detection.",
+ &setlist);
+ c->function.sfunc = set_gnutarget_command;
+ add_show_from_set (c, &showlist);
+
+ if (getenv ("GNUTARGET"))
+ set_gnutarget (getenv ("GNUTARGET"));
+ else
+ set_gnutarget ("auto");
+}
diff --git a/gnu/usr.bin/gdb/gdb/coredep.c b/gnu/usr.bin/gdb/gdb/coredep.c
new file mode 100644
index 000000000000..d94fd9820c9d
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/coredep.c
@@ -0,0 +1,118 @@
+/* Extract registers from a "standard" core file, for GDB.
+ Copyright (C) 1988-1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 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 <sys/types.h>
+#include <sys/param.h>
+#include "gdbcore.h"
+
+/* These are needed on various systems to expand REGISTER_U_ADDR. */
+#ifndef USG
+#include <sys/dir.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/user.h>
+#ifndef NO_PTRACE_H
+# ifdef PTRACE_IN_WRONG_PLACE
+# include <ptrace.h>
+# else /* !PTRACE_IN_WRONG_PLACE */
+# include <sys/ptrace.h>
+# endif /* !PTRACE_IN_WRONG_PLACE */
+#endif /* NO_PTRACE_H */
+#endif
+
+#ifdef NEED_SYS_CORE_H
+#include <sys/core.h>
+#endif
+
+/* Extract the register values out of the core file and store
+ them where `read_register' will find them.
+
+ CORE_REG_SECT points to the register values themselves, read into memory.
+ CORE_REG_SIZE is the size of that area.
+ WHICH says which set of registers we are handling (0 = int, 2 = float
+ on machines where they are discontiguous).
+ REG_ADDR is the offset from u.u_ar0 to the register values relative to
+ core_reg_sect. This is used with old-fashioned core files to
+ locate the registers in a large upage-plus-stack ".reg" section.
+ Original upage address X is at location core_reg_sect+x+reg_addr.
+ */
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned reg_addr;
+{
+ register int regno;
+ register unsigned int addr;
+ int bad_reg = -1;
+ register reg_ptr = -reg_addr; /* Original u.u_ar0 is -reg_addr. */
+
+ /* If u.u_ar0 was an absolute address in the core file, relativize it now,
+ so we can use it as an offset into core_reg_sect. When we're done,
+ "register 0" will be at core_reg_sect+reg_ptr, and we can use
+ register_addr to offset to the other registers. If this is a modern
+ core file without a upage, reg_ptr will be zero and this is all a big
+ NOP. */
+ if (reg_ptr > core_reg_size)
+ reg_ptr -= KERNEL_U_ADDR;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ addr = register_addr (regno, reg_ptr);
+ 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/gnu/usr.bin/gdb/gdb/corelow.c b/gnu/usr.bin/gdb/gdb/corelow.c
new file mode 100644
index 000000000000..1cebc48985ec
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/corelow.c
@@ -0,0 +1,328 @@
+/* Core dump and executable file functions below target vector, for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.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"
+
+static void
+core_files_info PARAMS ((struct target_ops *));
+
+#ifdef SOLIB_ADD
+static int
+solib_add_stub PARAMS ((char *));
+#endif
+
+static void
+core_close PARAMS ((int));
+
+static void
+get_core_registers PARAMS ((int));
+
+/* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+/* ARGSUSED */
+static void
+core_close (quitting)
+ int quitting;
+{
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
+ if (core_bfd) {
+ free (bfd_get_filename (core_bfd));
+ bfd_close (core_bfd);
+ core_bfd = NULL;
+#ifdef CLEAR_SOLIB
+ CLEAR_SOLIB ();
+#endif
+ if (core_ops.to_sections) {
+ free ((PTR)core_ops.to_sections);
+ core_ops.to_sections = NULL;
+ core_ops.to_sections_end = NULL;
+ }
+ }
+}
+
+#ifdef SOLIB_ADD
+/* Stub function for catch_errors around shared library hacking. */
+
+static int
+solib_add_stub (from_tty)
+ char *from_tty;
+{
+ SOLIB_ADD (NULL, (int)from_tty, &core_ops);
+ return 0;
+}
+#endif /* SOLIB_ADD */
+
+/* Look for sections whose names start with `.reg/' so that we can extract the
+ list of threads in a core file. */
+
+static void
+add_to_thread_list (abfd, asect, reg_sect_arg)
+ bfd *abfd;
+ asection *asect;
+ PTR reg_sect_arg;
+{
+ int thread_id;
+ asection *reg_sect = (asection *) reg_sect_arg;
+
+ if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0)
+ return;
+
+ thread_id = atoi (bfd_section_name (abfd, asect) + 5);
+
+ add_thread (thread_id);
+
+/* Warning, Will Robinson, looking at BFD private data! */
+
+ if (asect->filepos == reg_sect->filepos) /* Did we find .reg? */
+ inferior_pid = thread_id; /* Yes, make it current */
+}
+
+/* This routine opens and sets up the core file bfd */
+
+void
+core_open (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ const char *p;
+ int siggy;
+ struct cleanup *old_chain;
+ char *temp;
+ bfd *temp_bfd;
+ int ontop;
+ int scratch_chan;
+
+ target_preopen (from_tty);
+ 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, NULL);
+ free (filename);
+ filename = temp;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ scratch_chan = open (filename, write_files? O_RDWR: O_RDONLY, 0);
+ if (scratch_chan < 0)
+ perror_with_name (filename);
+
+ temp_bfd = bfd_fdopenr (filename, gnutarget, scratch_chan);
+ if (temp_bfd == NULL)
+ {
+ perror_with_name (filename);
+ }
+
+ if (!bfd_check_format (temp_bfd, bfd_core))
+ {
+ /* Do it after the err msg */
+ make_cleanup (bfd_close, temp_bfd);
+ error ("\"%s\" is not a core dump: %s", filename, bfd_errmsg(bfd_error));
+ }
+
+ /* 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_ops.to_sections,
+ &core_ops.to_sections_end))
+ error ("Can't find sections in `%s': %s", bfd_get_filename(core_bfd),
+ bfd_errmsg (bfd_error));
+
+ ontop = !push_target (&core_ops);
+ discard_cleanups (old_chain);
+
+ p = bfd_core_file_failing_command (core_bfd);
+ if (p)
+ printf_filtered ("Core was generated by `%s'.\n", p);
+
+ siggy = bfd_core_file_failing_signal (core_bfd);
+ if (siggy > 0)
+ printf_filtered ("Program terminated with signal %d, %s.\n", siggy,
+ safe_strsignal (siggy));
+
+ /* Build up thread list from BFD sections. */
+
+ init_thread_list ();
+ bfd_map_over_sections (core_bfd, add_to_thread_list,
+ bfd_get_section_by_name (core_bfd, ".reg"));
+
+ if (ontop) {
+ /* Fetch all registers from core file */
+ target_fetch_registers (-1);
+
+ /* Add symbols and section mappings for any shared libraries */
+#ifdef SOLIB_ADD
+ catch_errors (solib_add_stub, (char *)from_tty, (char *)0,
+ RETURN_MASK_ALL);
+#endif
+
+ /* Now, set up the frame cache, and print the top of stack */
+ set_current_frame (create_new_frame (read_fp (),
+ read_pc ()));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+ } else {
+ warning (
+"you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''", current_target->to_longname);
+ }
+}
+
+void
+core_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Too many arguments");
+ unpush_target (&core_ops);
+ reinit_frame_cache ();
+ if (from_tty)
+ printf_filtered ("No core file now.\n");
+}
+
+/* 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. */
+
+/* We just get all the registers, so we don't use regno. */
+/* ARGSUSED */
+static void
+get_core_registers (regno)
+ int regno;
+{
+ sec_ptr reg_sec;
+ unsigned size;
+ char *the_regs;
+ char secname[10];
+
+ /* Thread support. If inferior_pid is non-zero, then we have found a core
+ file with threads (or multiple processes). In that case, we need to
+ use the appropriate register section, else we just use `.reg'. */
+
+ /* XXX - same thing needs to be done for floating-point (.reg2) sections. */
+
+ if (inferior_pid)
+ sprintf (secname, ".reg/%d", inferior_pid);
+ else
+ strcpy (secname, ".reg");
+
+ reg_sec = bfd_get_section_by_name (core_bfd, secname);
+ if (!reg_sec) goto cant;
+ size = bfd_section_size (core_bfd, reg_sec);
+ the_regs = alloca (size);
+ if (bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, size))
+ {
+ fetch_core_registers (the_regs, size, 0,
+ (unsigned) bfd_section_vma (abfd,reg_sec));
+ }
+ else
+ {
+cant:
+ fprintf_filtered (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, (file_ptr)0,
+ size))
+ {
+ fetch_core_registers (the_regs, size, 2,
+ (unsigned) bfd_section_vma (abfd,reg_sec));
+ }
+ else
+ {
+ fprintf_filtered (stderr, "Couldn't fetch register set 2 from core file: %s\n",
+ bfd_errmsg (bfd_error));
+ }
+ }
+ registers_fetched();
+}
+
+static void
+core_files_info (t)
+ struct target_ops *t;
+{
+ print_section_info (t, core_bfd);
+}
+
+/* If mourn is being called in all the right places, this could be say
+ `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */
+
+static int
+ignore (addr, contents)
+ CORE_ADDR addr;
+ char *contents;
+{
+}
+
+struct target_ops core_ops = {
+ "core", "Local core dump file",
+ "Use a core file as a target. Specify the filename of the core file.",
+ core_open, core_close,
+ find_default_attach, core_detach, 0, 0, /* resume, wait */
+ get_core_registers,
+ 0, 0, /* store_regs, prepare_to_store */
+ xfer_memory, core_files_info,
+ ignore, ignore, /* core_insert_breakpoint, core_remove_breakpoint, */
+ 0, 0, 0, 0, 0, /* terminal stuff */
+ 0, 0, 0, /* kill, load, lookup sym */
+ find_default_create_inferior, 0, /* mourn_inferior */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ core_stratum, 0, /* next */
+ 0, 1, 1, 1, 0, /* all mem, mem, stack, regs, exec */
+ 0, 0, /* section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_corelow()
+{
+ add_target (&core_ops);
+}
diff --git a/gnu/usr.bin/gdb/gdb/cp-valprint.c b/gnu/usr.bin/gdb/gdb/cp-valprint.c
new file mode 100644
index 000000000000..47b38f803d9b
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/cp-valprint.c
@@ -0,0 +1,484 @@
+/* Support for printing C++ values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "demangle.h"
+
+int vtblprint; /* Controls printing of vtbl's */
+int objectprint; /* Controls looking up an object's derived type
+ using what we find in its vtables. */
+struct obstack dont_print_obstack;
+
+static void
+cplus_print_value PARAMS ((struct type *, char *, FILE *, int, int,
+ enum val_prettyprint, struct type **));
+
+/* BEGIN-FIXME: Hooks into typeprint.c, find a better home for prototypes. */
+
+extern void
+c_type_print_base PARAMS ((struct type *, FILE *, int, int));
+
+extern void
+c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int));
+
+extern void
+cp_type_print_method_args PARAMS ((struct type **, char *, char *, int,
+ FILE *));
+
+extern struct obstack dont_print_obstack;
+
+/* END-FIXME */
+
+
+/* BEGIN-FIXME: Hooks into c-valprint.c */
+
+extern int
+c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, int,
+ enum val_prettyprint));
+/* END-FIXME */
+
+
+void
+cp_print_class_method (valaddr, type, stream)
+ char *valaddr;
+ struct type *type;
+ FILE *stream;
+{
+ struct type *domain;
+ struct fn_field *f = NULL;
+ int j = 0;
+ int len2;
+ int offset;
+ char *kind = "";
+ CORE_ADDR addr;
+ struct symbol *sym;
+ unsigned len;
+ unsigned int i;
+
+ check_stub_type (TYPE_TARGET_TYPE (type));
+ domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
+ if (domain == (struct type *)NULL)
+ {
+ fprintf_filtered (stream, "<unknown>");
+ return;
+ }
+ addr = unpack_pointer (lookup_pointer_type (builtin_type_void), valaddr);
+ if (METHOD_PTR_IS_VIRTUAL (addr))
+ {
+ offset = METHOD_PTR_TO_VOFFSET (addr);
+ 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) == offset)
+ {
+ kind = "virtual ";
+ goto common;
+ }
+ }
+ }
+ }
+ else
+ {
+ sym = find_pc_function (addr);
+ 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 (TYPE_FN_FIELD_STUB (f, j))
+ check_stub_method (domain, i, j);
+ if (STREQ (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
+ {
+ goto common;
+ }
+ }
+ }
+ }
+ common:
+ if (i < len)
+ {
+ fprintf_filtered (stream, "&");
+ c_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)
+ {
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
+ TYPE_FN_FIELDLIST_NAME (domain, i),
+ 0, stream);
+ }
+ else
+ {
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "",
+ TYPE_FN_FIELDLIST_NAME (domain, i),
+ 0, stream);
+ }
+ }
+ else
+ {
+ fprintf_filtered (stream, "(");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, ") %d", (int) addr >> 3);
+ }
+}
+
+/* Return truth value for assertion that TYPE is of the type
+ "pointer to virtual function". */
+
+int
+cp_is_vtbl_ptr_type(type)
+ struct type *type;
+{
+ char *typename = type_name_no_tag (type);
+ /* This was what it was for gcc 2.4.5 and earlier. */
+ static const char vtbl_ptr_name_old[] =
+ { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e', 0 };
+ /* It was changed to this after 2.4.5. */
+ static const char vtbl_ptr_name[] =
+ { '_','_','v','t','b','l','_','p','t','r','_','t','y','p','e', 0 };
+
+ return (typename != NULL
+ && (STREQ (typename, vtbl_ptr_name)
+ || STREQ (typename, vtbl_ptr_name_old)));
+}
+
+/* Return truth value for the assertion that TYPE is of the type
+ "pointer to virtual function table". */
+
+int
+cp_is_vtbl_member(type)
+ struct type *type;
+{
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ else
+ return 0;
+
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT)
+ /* Virtual functions tables are full of pointers to virtual functions. */
+ return cp_is_vtbl_ptr_type (TYPE_TARGET_TYPE (type));
+ return 0;
+}
+
+/* Mutually recursive subroutines of cplus_print_value and c_val_print to
+ print out a structure's fields: cp_print_value_fields and cplus_print_value.
+
+ TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the
+ same meanings as in cplus_print_value and c_val_print.
+
+ DONT_PRINT is an array of baseclass types that we
+ should not print, or zero if called from top level. */
+
+void
+cp_print_value_fields (type, valaddr, stream, format, recurse, pretty,
+ dont_print)
+ struct type *type;
+ char *valaddr;
+ FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+ struct type **dont_print;
+{
+ int i, len, n_baseclasses;
+
+ check_stub_type (type);
+
+ 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_print_value (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)
+ {
+ if (pretty)
+ {
+ 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);
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ fputs_filtered ("\" \"", stream);
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ fputs_filtered ("\") \"", stream);
+ }
+ else
+ {
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ fputs_filtered (" = ", stream);
+ }
+ if (TYPE_FIELD_PACKED (type, i))
+ {
+ value v;
+
+ /* Bitfields require special handling, especially due to byte
+ order problems. */
+ v = value_from_longest (TYPE_FIELD_TYPE (type, i),
+ unpack_field_as_long (type, valaddr, i));
+
+ c_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0,
+ stream, format, 0, recurse + 1, pretty);
+ }
+ else
+ {
+ c_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_print_value (type, valaddr, stream, format, recurse, pretty, dont_print)
+ struct type *type;
+ char *valaddr;
+ FILE *stream;
+ int 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;
+ int err;
+ char *basename = TYPE_NAME (TYPE_BASECLASS (type, i));
+
+ 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));
+ }
+
+ /* Fix to use baseclass_offset instead. FIXME */
+ baddr = baseclass_addr (type, i, valaddr, 0, &err);
+ if (err == 0 && baddr == 0)
+ error ("could not find virtual baseclass %s\n",
+ basename ? basename : "");
+
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ fputs_filtered ("<", stream);
+ /* Not sure what the best notation is in the case where there is no
+ baseclass name. */
+ fputs_filtered (basename ? basename : "", stream);
+ fputs_filtered ("> = ", stream);
+ if (err != 0)
+ fprintf_filtered (stream,
+ "<invalid address 0x%lx>", (unsigned long) baddr);
+ else
+ cp_print_value_fields (TYPE_BASECLASS (type, i), baddr, stream, format,
+ recurse, pretty,
+ (struct type **) obstack_base (&dont_print_obstack));
+ fputs_filtered (", ", stream);
+
+ 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;
+ }
+}
+
+void
+cp_print_class_member (valaddr, domain, stream, prefix)
+ char *valaddr;
+ struct type *domain;
+ FILE *stream;
+ char *prefix;
+{
+
+ /* 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;
+ register unsigned int i;
+ unsigned len = TYPE_NFIELDS (domain);
+ /* @@ Make VAL into bit offset */
+ LONGEST 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 & 0x7)
+ bits = 1;
+ else
+ extra >>= 3;
+ break;
+ }
+ }
+ if (i < len)
+ {
+ char *name;
+ fprintf_filtered (stream, prefix);
+ name = type_name_no_tag (domain);
+ if (name)
+ fputs_filtered (name, stream);
+ else
+ c_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)");
+ }
+ else
+ fprintf_filtered (stream, "%d", val >> 3);
+}
+
+void
+_initialize_cp_valprint ()
+{
+ add_show_from_set
+ (add_set_cmd ("vtbl", class_support, var_boolean, (char *)&vtblprint,
+ "Set printing of C++ virtual function tables.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("object", class_support, var_boolean, (char *)&objectprint,
+ "Set printing of object's derived type based on vtable info.",
+ &setprintlist),
+ &showprintlist);
+
+ /* Give people the defaults which they are used to. */
+ objectprint = 0;
+ vtblprint = 0;
+ obstack_begin (&dont_print_obstack, 32 * sizeof (struct type *));
+}
diff --git a/gnu/usr.bin/gdb/gdb/dbxread.c b/gnu/usr.bin/gdb/gdb/dbxread.c
new file mode 100644
index 000000000000..7f4ef2632abb
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/dbxread.c
@@ -0,0 +1,2234 @@
+/* Read dbx symbol tables and convert to internal format, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This module provides three functions: dbx_symfile_init,
+ which initializes to read a symbol file; dbx_new_init, which
+ discards existing cached information when all symbols are being
+ discarded; and dbx_symfile_read, which reads a symbol table
+ from a file.
+
+ dbx_symfile_read only does the minimum work necessary for letting the
+ user "name" things symbolically; it does not read the entire symtab.
+ Instead, it reads the external and static symbols and puts 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 symbols
+ for real. dbx_psymtab_to_symtab() is the function that does this */
+
+#include "defs.h"
+#include <string.h>
+
+#if defined(USG) || defined(__CYGNUSCLIB__)
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#include <obstack.h>
+#include <sys/param.h>
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#include <sys/stat.h>
+#include <ctype.h>
+#include "symtab.h"
+#include "breakpoint.h"
+#include "command.h"
+#include "target.h"
+#include "gdbcore.h" /* for bfd stuff */
+#include "libbfd.h" /* FIXME Secret internal BFD stuff (bfd_read) */
+#include "libaout.h" /* FIXME Secret internal BFD stuff for a.out */
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+#include "demangle.h"
+#include "language.h" /* Needed inside partial-stab.h */
+#include "complaints.h"
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */
+
+#if !defined (SEEK_SET)
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#endif
+
+/* Each partial symbol table entry contains a pointer to private data for the
+ read_symtab() function to use when expanding a partial symbol table entry
+ to a full symbol table entry.
+
+ For dbxread this structure contains the offset within the file 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 file's symbols). It also contains
+ further information needed to locate the symbols if they are in an ELF file.
+
+ If ldsymlen is 0, the only reason for this thing's existence is the
+ dependency list. Nothing else will happen when it is read in. */
+
+#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
+#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen)
+#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private))
+#define SYMBOL_SIZE(p) (SYMLOC(p)->symbol_size)
+#define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
+#define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
+#define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
+
+struct symloc {
+ int ldsymoff;
+ int ldsymlen;
+ int symbol_size;
+ int symbol_offset;
+ int string_offset;
+ int file_string_offset;
+};
+
+/* 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
+
+/* Macro for name of symbol to indicate a file compiled with gcc2. */
+#ifndef GCC2_COMPILED_FLAG_SYMBOL
+#define GCC2_COMPILED_FLAG_SYMBOL "gcc2_compiled."
+#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
+
+/* Remember what we deduced to be the source language of this psymtab. */
+
+static enum language psymtab_language = language_unknown;
+
+/* Nonzero means give verbose info on gdb action. From main.c. */
+extern int info_verbose;
+
+/* The BFD for this file -- implicit parameter to next_symbol_text. */
+
+static bfd *symfile_bfd;
+
+/* The size of each symbol in the symbol file (in external form).
+ This is set by dbx_symfile_read when building psymtabs, and by
+ dbx_psymtab_to_symtab when building symtabs. */
+
+static unsigned symbol_size;
+
+/* This is the offset of the symbol table in the executable file */
+static unsigned symbol_table_offset;
+
+/* This is the offset of the string table in the executable file */
+static unsigned string_table_offset;
+
+/* For elf+stab executables, the n_strx field is not a simple index
+ into the string table. Instead, each .o file has a base offset
+ in the string table, and the associated symbols contain offsets
+ from this base. The following two variables contain the base
+ offset for the current and next .o files. */
+static unsigned int file_string_table_offset;
+static unsigned int next_file_string_table_offset;
+
+/* Complaints about the symbols we have encountered. */
+
+struct complaint lbrac_complaint =
+ {"bad block start address patched", 0, 0};
+
+struct complaint string_table_offset_complaint =
+ {"bad string table offset in symbol %d", 0, 0};
+
+struct complaint unknown_symtype_complaint =
+ {"unknown symbol type %s", 0, 0};
+
+struct complaint unknown_symchar_complaint =
+ {"unknown symbol type character `%c'", 0, 0};
+
+struct complaint lbrac_rbrac_complaint =
+ {"block start larger than block end", 0, 0};
+
+struct complaint lbrac_unmatched_complaint =
+ {"unmatched N_LBRAC before symtab pos %d", 0, 0};
+
+struct complaint lbrac_mismatch_complaint =
+ {"N_LBRAC/N_RBRAC symbol mismatch at symtab pos %d", 0, 0};
+
+struct complaint repeated_header_complaint =
+ {"\"repeated\" header file not previously seen, at symtab pos %d", 0, 0};
+
+struct complaint repeated_header_name_complaint =
+ {"\"repeated\" header file not previously seen, named %s", 0, 0};
+
+/* 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;
+
+/* Local function prototypes */
+
+static void
+free_header_files PARAMS ((void));
+
+static void
+init_header_files PARAMS ((void));
+
+static void
+read_ofile_symtab PARAMS ((struct partial_symtab *));
+
+static void
+dbx_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+static void
+dbx_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+
+static void
+read_dbx_symtab PARAMS ((struct section_offsets *, struct objfile *,
+ CORE_ADDR, int));
+
+static void
+free_bincl_list PARAMS ((struct objfile *));
+
+static struct partial_symtab *
+find_corresponding_bincl_psymtab PARAMS ((char *, int));
+
+static void
+add_bincl_to_list PARAMS ((struct partial_symtab *, char *, int));
+
+static void
+init_bincl_list PARAMS ((int, struct objfile *));
+
+static void
+init_psymbol_list PARAMS ((struct objfile *));
+
+static char *
+dbx_next_symbol_text PARAMS ((void));
+
+static void
+fill_symbuf PARAMS ((bfd *));
+
+static void
+dbx_symfile_init PARAMS ((struct objfile *));
+
+static void
+dbx_new_init PARAMS ((struct objfile *));
+
+static void
+dbx_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+dbx_symfile_finish PARAMS ((struct objfile *));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, int, struct objfile *));
+
+static void
+add_new_header_file PARAMS ((char *, int));
+
+static void
+add_old_header_file PARAMS ((char *, int));
+
+static void
+add_this_object_header_file PARAMS ((int));
+
+/* Free up old header file tables */
+
+static void
+free_header_files ()
+{
+ register int i;
+
+ if (header_files != NULL)
+ {
+ for (i = 0; i < n_header_files; i++)
+ {
+ free (header_files[i].name);
+ }
+ free ((PTR)header_files);
+ header_files = NULL;
+ n_header_files = 0;
+ }
+ if (this_object_header_files)
+ {
+ free ((PTR)this_object_header_files);
+ this_object_header_files = NULL;
+ }
+ n_allocated_header_files = 0;
+ n_allocated_this_object_header_files = 0;
+}
+
+/* Allocate new header file tables */
+
+static void
+init_header_files ()
+{
+ n_header_files = 0;
+ n_allocated_header_files = 10;
+ header_files = (struct header_file *)
+ xmalloc (10 * sizeof (struct header_file));
+
+ n_allocated_this_object_header_files = 10;
+ this_object_header_files = (int *) xmalloc (10 * sizeof (int));
+}
+
+/* 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 ((char *) 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 (STREQ (p[i].name, name) && instance == p[i].instance)
+ {
+ add_this_object_header_file (i);
+ return;
+ }
+ complain (&repeated_header_complaint, symnum);
+ complain (&repeated_header_name_complaint, name);
+}
+
+/* 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;
+
+ /* 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 ((char *) 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 *));
+ memset (header_files[i].vector, 0, 10 * sizeof (struct type *));
+
+ add_this_object_header_file (i);
+}
+
+#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 *));
+ memset (&f->vector[f->length / 2],
+ '\0', f->length * sizeof (struct type *) / 2);
+ }
+ return &f->vector[index];
+}
+#endif
+
+static void
+record_minimal_symbol (name, address, type, objfile)
+ char *name;
+ CORE_ADDR address;
+ int type;
+ struct objfile *objfile;
+{
+ enum minimal_symbol_type ms_type;
+
+ switch (type)
+ {
+ case N_TEXT | N_EXT: ms_type = mst_text; break;
+ case N_DATA | N_EXT: ms_type = mst_data; break;
+ case N_BSS | N_EXT: ms_type = mst_bss; break;
+ case N_ABS | N_EXT: ms_type = mst_abs; break;
+#ifdef N_SETV
+ case N_SETV | N_EXT: ms_type = mst_data; break;
+ case N_SETV:
+ /* I don't think this type actually exists; since a N_SETV is the result
+ of going over many .o files, it doesn't make sense to have one
+ file local. */
+ ms_type = mst_file_data;
+ break;
+#endif
+ case N_TEXT:
+ /* Don't put gcc_compiled, __gnu_compiled_cplus, and friends into
+ the minimal symbols, because if there is also another symbol
+ at the same address (e.g. the first function of the file),
+ lookup_minimal_symbol_by_pc would have no way of getting the
+ right one. */
+ if (name[0] == 'g'
+ && (strcmp (name, GCC_COMPILED_FLAG_SYMBOL) == 0
+ || strcmp (name, GCC2_COMPILED_FLAG_SYMBOL) == 0))
+ return;
+
+ {
+ char *tempstring = name;
+ if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
+ ++tempstring;
+ if (STREQN (tempstring, "__gnu_compiled", 14))
+ return;
+ }
+
+ case N_NBTEXT:
+ case N_FN:
+ case N_FN_SEQ:
+ ms_type = mst_file_text;
+ break;
+
+ case N_DATA:
+ ms_type = mst_file_data;
+
+ /* Check for __DYNAMIC, which is used by Sun shared libraries.
+ Record it as global even if it's local, not global, so
+ lookup_minimal_symbol can find it. We don't check symbol_leading_char
+ because for SunOS4 it always is '_'. */
+ if (name[8] == 'C' && STREQ ("__DYNAMIC", name))
+ ms_type = mst_data;
+
+ /* Same with virtual function tables, both global and static. */
+ {
+ char *tempstring = name;
+ if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
+ ++tempstring;
+ if (VTBL_PREFIX_P ((tempstring)))
+ ms_type = mst_data;
+ }
+ break;
+
+ case N_BSS:
+ ms_type = mst_file_bss;
+ break;
+
+ default: ms_type = mst_unknown; break;
+ }
+
+ prim_record_minimal_symbol
+ (obsavestring (name, strlen (name), &objfile -> symbol_obstack),
+ address,
+ ms_type);
+}
+
+/* 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 objfile structure.
+
+ SECTION_OFFSETS contains offsets relative to which the symbols in the
+ various sections are (depending where the sections were actually loaded).
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file). */
+
+static void
+dbx_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline; /* FIXME comments above */
+{
+ bfd *sym_bfd;
+ int val;
+ struct cleanup *back_to;
+
+ sym_bfd = objfile->obfd;
+ val = bfd_seek (objfile->obfd, DBX_SYMTAB_OFFSET (objfile), SEEK_SET);
+ if (val < 0)
+ perror_with_name (objfile->name);
+
+ /* If we are reinitializing, or if we have never loaded syms yet, init */
+ if (mainline || objfile->global_psymbols.size == 0 || objfile->static_psymbols.size == 0)
+ init_psymbol_list (objfile);
+
+ symbol_size = DBX_SYMBOL_SIZE (objfile);
+ symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
+
+ pending_blocks = 0;
+ back_to = make_cleanup (really_free_pendings, 0);
+
+ init_minimal_symbol_collection ();
+ make_cleanup (discard_minimal_symbols, 0);
+
+ /* Now that the symbol table data of the executable file are all in core,
+ process them and define symbols accordingly. */
+
+ read_dbx_symtab (section_offsets, objfile,
+ bfd_section_vma (sym_bfd, DBX_TEXT_SECT (objfile)),
+ bfd_section_size (sym_bfd, DBX_TEXT_SECT (objfile)));
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ if (!have_partial_symbols ()) {
+ wrap_here ("");
+ printf_filtered ("(no debugging symbols found)...");
+ wrap_here ("");
+ }
+
+ do_cleanups (back_to);
+}
+
+/* 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). */
+
+static void
+dbx_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+ init_header_files ();
+}
+
+
+/* dbx_symfile_init ()
+ is the dbx-specific initialization routine for reading symbols.
+ It is passed a struct objfile 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. */
+
+#define DBX_STRINGTAB_SIZE_SIZE sizeof(long) /* FIXME */
+
+static void
+dbx_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ unsigned char size_temp[DBX_STRINGTAB_SIZE_SIZE];
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_stab_info = (PTR)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+
+ /* FIXME POKING INSIDE BFD DATA STRUCTURES */
+#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 */
+
+ DBX_SYMFILE_INFO (objfile)->stab_section_info = NULL;
+ DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!DBX_TEXT_SECT (objfile))
+ error ("Can't find .text section in symbol file");
+
+ DBX_SYMBOL_SIZE (objfile) = obj_symbol_entry_size (sym_bfd);
+ DBX_SYMCOUNT (objfile) = bfd_get_symcount (sym_bfd);
+ DBX_SYMTAB_OFFSET (objfile) = SYMBOL_TABLE_OFFSET;
+
+ /* Read the string table and stash it away in the psymbol_obstack. It is
+ only needed as long as we need to expand psymbols into full symbols,
+ so when we blow away the psymbol the string table goes away as well.
+ Note that gdb used to use the results of attempting to malloc the
+ string table, based on the size it read, as a form of sanity check
+ for botched byte swapping, on the theory that a byte swapped string
+ table size would be so totally bogus that the malloc would fail. Now
+ that we put in on the psymbol_obstack, we can't do this since gdb gets
+ a fatal error (out of virtual memory) if the size is bogus. We can
+ however at least check to see if the size is less than the size of
+ the size field itself, or larger than the size of the entire file.
+ Note that all valid string tables have a size greater than zero, since
+ the bytes used to hold the size are included in the count. */
+
+ if (STRING_TABLE_OFFSET == 0)
+ {
+ /* It appears that with the existing bfd code, STRING_TABLE_OFFSET
+ will never be zero, even when there is no string table. This
+ would appear to be a bug in bfd. */
+ DBX_STRINGTAB_SIZE (objfile) = 0;
+ DBX_STRINGTAB (objfile) = NULL;
+ }
+ else
+ {
+ val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+
+ memset ((PTR) size_temp, 0, sizeof (size_temp));
+ val = bfd_read ((PTR) size_temp, sizeof (size_temp), 1, sym_bfd);
+ if (val < 0)
+ {
+ perror_with_name (name);
+ }
+ else if (val == 0)
+ {
+ /* With the existing bfd code, STRING_TABLE_OFFSET will be set to
+ EOF if there is no string table, and attempting to read the size
+ from EOF will read zero bytes. */
+ DBX_STRINGTAB_SIZE (objfile) = 0;
+ DBX_STRINGTAB (objfile) = NULL;
+ }
+ else
+ {
+ /* Read some data that would appear to be the string table size.
+ If there really is a string table, then it is probably the right
+ size. Byteswap if necessary and validate the size. Note that
+ the minimum is DBX_STRINGTAB_SIZE_SIZE. If we just read some
+ random data that happened to be at STRING_TABLE_OFFSET, because
+ bfd can't tell us there is no string table, the sanity checks may
+ or may not catch this. */
+ DBX_STRINGTAB_SIZE (objfile) = bfd_h_get_32 (sym_bfd, size_temp);
+
+ if (DBX_STRINGTAB_SIZE (objfile) < sizeof (size_temp)
+ || DBX_STRINGTAB_SIZE (objfile) > bfd_get_size (sym_bfd))
+ error ("ridiculous string table size (%d bytes).",
+ DBX_STRINGTAB_SIZE (objfile));
+
+ DBX_STRINGTAB (objfile) =
+ (char *) obstack_alloc (&objfile -> psymbol_obstack,
+ DBX_STRINGTAB_SIZE (objfile));
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = bfd_read (DBX_STRINGTAB (objfile), DBX_STRINGTAB_SIZE (objfile), 1,
+ sym_bfd);
+ if (val != DBX_STRINGTAB_SIZE (objfile))
+ perror_with_name (name);
+ }
+ }
+}
+
+/* Perform any local cleanups required when we are done with a particular
+ objfile. I.E, we are in the process of discarding all symbol information
+ for an objfile, freeing up all memory held for it, and unlinking the
+ objfile struct from the global list of known objfiles. */
+
+static void
+dbx_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sym_stab_info != NULL)
+ {
+ mfree (objfile -> md, objfile->sym_stab_info);
+ }
+ free_header_files ();
+}
+
+
+/* Buffer for reading the symbol table entries. */
+static struct internal_nlist symbuf[4096];
+static int symbuf_idx;
+static int symbuf_end;
+
+/* Name of last function encountered. Used in Solaris to approximate
+ object file boundaries. */
+static char *last_function_name;
+
+/* 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 void
+fill_symbuf (sym_bfd)
+ bfd *sym_bfd;
+{
+ int nbytes = bfd_read ((PTR)symbuf, sizeof (symbuf), 1, sym_bfd);
+ if (nbytes < 0)
+ perror_with_name (bfd_get_filename (sym_bfd));
+ else if (nbytes == 0)
+ error ("Premature end of file reading symbol table");
+ symbuf_end = nbytes / symbol_size;
+ symbuf_idx = 0;
+}
+
+#define SWAP_SYMBOL(symp, abfd) \
+ { \
+ (symp)->n_strx = bfd_h_get_32(abfd, \
+ (unsigned char *)&(symp)->n_strx); \
+ (symp)->n_desc = bfd_h_get_16 (abfd, \
+ (unsigned char *)&(symp)->n_desc); \
+ (symp)->n_value = bfd_h_get_32 (abfd, \
+ (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 *
+dbx_next_symbol_text ()
+{
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (symfile_bfd);
+ symnum++;
+ SWAP_SYMBOL(&symbuf[symbuf_idx], symfile_bfd);
+ return symbuf[symbuf_idx++].n_strx + stringtab_global
+ + file_string_table_offset;
+}
+
+/* Initializes storage for all of the partial symbols that will be
+ created by read_dbx_symtab and subsidiaries. */
+
+static void
+init_psymbol_list (objfile)
+ struct objfile *objfile;
+{
+ /* Free any previously allocated psymbol lists. */
+ if (objfile -> global_psymbols.list)
+ mfree (objfile -> md, (PTR)objfile -> global_psymbols.list);
+ if (objfile -> static_psymbols.list)
+ mfree (objfile -> md, (PTR)objfile -> 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 */
+ objfile -> global_psymbols.size = DBX_SYMCOUNT (objfile) / 10;
+ objfile -> static_psymbols.size = DBX_SYMCOUNT (objfile) / 10;
+ objfile -> global_psymbols.next = objfile -> global_psymbols.list = (struct partial_symbol *)
+ xmmalloc (objfile -> md, objfile -> global_psymbols.size * sizeof (struct partial_symbol));
+ objfile -> static_psymbols.next = objfile -> static_psymbols.list = (struct partial_symbol *)
+ xmmalloc (objfile -> md, objfile -> 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, objfile)
+ int number;
+ struct objfile *objfile;
+{
+ bincls_allocated = number;
+ next_bincl = bincl_list = (struct header_file_location *)
+ xmmalloc (objfile -> md, 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 *)
+ xmrealloc (pst->objfile->md, (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. */
+
+static 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
+ && STREQ (name, bincl->name))
+ return bincl->pst;
+
+ return (struct partial_symtab *) 0;
+}
+
+/* Free the storage allocated for the bincl list. */
+
+static void
+free_bincl_list (objfile)
+ struct objfile *objfile;
+{
+ mfree (objfile -> md, (PTR)bincl_list);
+ bincls_allocated = 0;
+}
+
+/* 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.
+ SYMFILE_NAME is the name of the file we are reading from
+ and SECTION_OFFSETS is the set of offsets for the various sections
+ of the file (a set of zeros if the mainline program). */
+
+static void
+read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+ CORE_ADDR text_addr;
+ int text_size;
+{
+ register struct internal_nlist *bufp = 0; /* =0 avoids gcc -Wall glitch */
+ register char *namestring;
+ int nsl;
+ int past_first_source_file = 0;
+ CORE_ADDR last_o_file_start = 0;
+ struct cleanup *back_to;
+ bfd *abfd;
+
+ /* 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;
+
+ /* FIXME. We probably want to change stringtab_global rather than add this
+ while processing every symbol entry. FIXME. */
+ file_string_table_offset = 0;
+ next_file_string_table_offset = 0;
+
+ stringtab_global = DBX_STRINGTAB (objfile);
+
+ 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 *));
+
+ /* Init bincl list */
+ init_bincl_list (20, objfile);
+ back_to = make_cleanup (free_bincl_list, objfile);
+
+ last_source_file = NULL;
+
+#ifdef END_OF_TEXT_DEFAULT
+ end_of_text_addr = END_OF_TEXT_DEFAULT;
+#else
+ end_of_text_addr = text_addr + section_offsets->offsets[SECT_OFF_TEXT]
+ + text_size; /* Relocate */
+#endif
+
+ symfile_bfd = objfile->obfd; /* For next_text_symbol */
+ abfd = objfile->obfd;
+ symbuf_end = symbuf_idx = 0;
+ next_symbol_text_func = dbx_next_symbol_text;
+
+ for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); 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 (abfd);
+ bufp = &symbuf[symbuf_idx++];
+
+ /*
+ * Special case to speed up readin.
+ */
+ if (bufp->n_type == (unsigned char)N_SLINE) continue;
+
+ SWAP_SYMBOL (bufp, abfd);
+
+ /* 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. */
+
+/*FIXME: Too many adds and indirections in here for the inner loop. */
+#define SET_NAMESTRING()\
+ if (((unsigned)bufp->n_strx + file_string_table_offset) >= \
+ DBX_STRINGTAB_SIZE (objfile)) { \
+ complain (&string_table_offset_complaint, symnum); \
+ namestring = "foo"; \
+ } else \
+ namestring = bufp->n_strx + file_string_table_offset + \
+ DBX_STRINGTAB (objfile)
+
+#define CUR_SYMBOL_TYPE bufp->n_type
+#define CUR_SYMBOL_VALUE bufp->n_value
+#define DBXREAD_ONLY
+#define START_PSYMTAB(ofile,secoff,fname,low,symoff,global_syms,static_syms)\
+ start_psymtab(ofile, secoff, fname, low, symoff, global_syms, static_syms)
+#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps)\
+ end_psymtab(pst,ilist,ninc,c_off,c_text,dep_list,n_deps)
+
+#include "partial-stab.h"
+ }
+
+ /* If there's stuff to be cleaned up, clean it up. */
+ if (DBX_SYMCOUNT (objfile) > 0 /* We have some syms */
+/*FIXME, does this have a bug at start address 0? */
+ && last_o_file_start
+ && objfile -> ei.entry_point < bufp->n_value
+ && objfile -> ei.entry_point >= last_o_file_start)
+ {
+ objfile -> ei.entry_file_lowpc = last_o_file_start;
+ objfile -> ei.entry_file_highpc = bufp->n_value;
+ }
+
+ if (pst)
+ {
+ end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum * symbol_size, end_of_text_addr,
+ dependency_list, dependencies_used);
+ }
+
+ do_cleanups (back_to);
+}
+
+/* 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). */
+
+
+struct partial_symtab *
+start_psymtab (objfile, section_offsets,
+ filename, textlow, ldsymoff, global_syms, static_syms)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ char *filename;
+ CORE_ADDR textlow;
+ int ldsymoff;
+ struct partial_symbol *global_syms;
+ struct partial_symbol *static_syms;
+{
+ struct partial_symtab *result =
+ start_psymtab_common(objfile, section_offsets,
+ filename, textlow, global_syms, static_syms);
+
+ result->read_symtab_private = (char *)
+ obstack_alloc (&objfile -> psymbol_obstack, sizeof (struct symloc));
+ LDSYMOFF(result) = ldsymoff;
+ result->read_symtab = dbx_psymtab_to_symtab;
+ SYMBOL_SIZE(result) = symbol_size;
+ SYMBOL_OFFSET(result) = symbol_table_offset;
+ STRING_OFFSET(result) = string_table_offset;
+ FILE_STRING_OFFSET(result) = file_string_table_offset;
+
+ /* If we're handling an ELF file, drag some section-relocation info
+ for this source file out of the ELF symbol table, to compensate for
+ Sun brain death. This replaces the section_offsets in this psymtab,
+ if successful. */
+ elfstab_offset_sections (objfile, result);
+
+ /* Deduce the source language from the filename for this psymtab. */
+ psymtab_language = deduce_language_from_filename (filename);
+
+ return result;
+}
+
+/* Close off the current usage of PST.
+ Returns PST or NULL if the partial symtab was empty and thrown away.
+
+ FIXME: List variables and peculiarities of same. */
+
+struct partial_symtab *
+end_psymtab (pst, include_list, num_includes, capping_symbol_offset,
+ capping_text, dependency_list, number_dependencies)
+ 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;
+ struct partial_symtab *p1;
+ struct objfile *objfile = pst -> objfile;
+
+ if (capping_symbol_offset != -1)
+ LDSYMLEN(pst) = capping_symbol_offset - LDSYMOFF(pst);
+ pst->texthigh = capping_text;
+
+ /* Under Solaris, the N_SO symbols always have a value of 0,
+ instead of the usual address of the .o file. Therefore,
+ we have to do some tricks to fill in texthigh and textlow.
+ The first trick is in partial-stab.h: if we see a static
+ or global function, and the textlow for the current pst
+ is still 0, then we use that function's address for
+ the textlow of the pst.
+
+ Now, to fill in texthigh, we remember the last function seen
+ in the .o file (also in partial-stab.h). Also, there's a hack in
+ bfd/elf.c and gdb/elfread.c to pass the ELF st_size field
+ to here via the misc_info field. Therefore, we can fill in
+ a reliable texthigh by taking the address plus size of the
+ last function in the file.
+
+ Unfortunately, that does not cover the case where the last function
+ in the file is static. See the paragraph below for more comments
+ on this situation.
+
+ Finally, if we have a valid textlow for the current file, we run
+ down the partial_symtab_list filling in previous texthighs that
+ are still unknown. */
+
+ if (pst->texthigh == 0 && last_function_name) {
+ char *p;
+ int n;
+ struct minimal_symbol *minsym;
+
+ p = strchr (last_function_name, ':');
+ if (p == NULL)
+ p = last_function_name;
+ n = p - last_function_name;
+ p = alloca (n + 1);
+ strncpy (p, last_function_name, n);
+ p[n] = 0;
+
+ minsym = lookup_minimal_symbol (p, objfile);
+
+ if (minsym) {
+ pst->texthigh = SYMBOL_VALUE_ADDRESS (minsym) +
+ (long) MSYMBOL_INFO (minsym);
+ } else {
+ /* This file ends with a static function, and it's
+ difficult to imagine how hard it would be to track down
+ the elf symbol. Luckily, most of the time no one will notice,
+ since the next file will likely be compiled with -g, so
+ the code below will copy the first fuction's start address
+ back to our texthigh variable. (Also, if this file is the
+ last one in a dynamically linked program, texthigh already
+ has the right value.) If the next file isn't compiled
+ with -g, then the last function in this file winds up owning
+ all of the text space up to the next -g file, or the end (minus
+ shared libraries). This only matters for single stepping,
+ and even then it will still work, except that it will single
+ step through all of the covered functions, instead of setting
+ breakpoints around them as it usualy does. This makes it
+ pretty slow, but at least it doesn't fail.
+
+ We can fix this with a fairly big change to bfd, but we need
+ to coordinate better with Cygnus if we want to do that. FIXME. */
+ }
+ last_function_name = NULL;
+ }
+
+ /* this test will be true if the last .o file is only data */
+ if (pst->textlow == 0)
+ pst->textlow = pst->texthigh;
+
+ /* If we know our own starting text address, then walk through all other
+ psymtabs for this objfile, and if any didn't know their ending text
+ address, set it to our starting address. Take care to not set our
+ own ending address to our starting address, nor to set addresses on
+ `dependency' files that have both textlow and texthigh zero. */
+ if (pst->textlow) {
+ ALL_OBJFILE_PSYMTABS (objfile, p1) {
+ if (p1->texthigh == 0 && p1->textlow != 0 && p1 != pst) {
+ p1->texthigh = pst->textlow;
+ /* if this file has only data, then make textlow match texthigh */
+ if (p1->textlow == 0)
+ p1->textlow = p1->texthigh;
+ }
+ }
+ }
+
+ /* End of kludge for patching Solaris textlow and texthigh. */
+
+
+ pst->n_global_syms =
+ objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset);
+ pst->n_static_syms =
+ objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset);
+
+ pst->number_of_dependencies = number_dependencies;
+ if (number_dependencies)
+ {
+ pst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ number_dependencies * sizeof (struct partial_symtab *));
+ memcpy (pst->dependencies, dependency_list,
+ number_dependencies * sizeof (struct partial_symtab *));
+ }
+ else
+ pst->dependencies = 0;
+
+ for (i = 0; i < num_includes; i++)
+ {
+ struct partial_symtab *subpst =
+ allocate_psymtab (include_list[i], objfile);
+
+ subpst->section_offsets = pst->section_offsets;
+ subpst->read_symtab_private =
+ (char *) obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct symloc));
+ LDSYMOFF(subpst) =
+ LDSYMLEN(subpst) =
+ subpst->textlow =
+ subpst->texthigh = 0;
+
+ /* We could save slight bits of space by only making one of these,
+ shared by the entire set of include files. FIXME-someday. */
+ subpst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->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->symtab = 0;
+ subpst->read_symtab = pst->read_symtab;
+ }
+
+ sort_pst_symbols (pst);
+
+ /* If there is already a psymtab or symtab for a file of this name, remove it.
+ (If there is a symtab, more drastic things also happen.)
+ This happens in VxWorks. */
+ free_named_symtabs (pst->filename);
+
+ if (num_includes == 0
+ && number_dependencies == 0
+ && pst->n_global_syms == 0
+ && pst->n_static_syms == 0) {
+ /* Throw away this psymtab, it's empty. We can't deallocate it, since
+ it is on the obstack, but we can forget to chain it on the list. */
+ struct partial_symtab *prev_pst;
+
+ /* First, snip it out of the psymtab chain */
+
+ if (pst->objfile->psymtabs == pst)
+ pst->objfile->psymtabs = pst->next;
+ else
+ for (prev_pst = pst->objfile->psymtabs; prev_pst; prev_pst = pst->next)
+ if (prev_pst->next == pst)
+ prev_pst->next = pst->next;
+
+ /* Next, put it on a free list for recycling */
+
+ pst->next = pst->objfile->free_psymtabs;
+ pst->objfile->free_psymtabs = pst;
+
+ /* Indicate that psymtab was thrown away. */
+ pst = (struct partial_symtab *)NULL;
+ }
+ return pst;
+}
+
+static void
+dbx_psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ 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 symtabs 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);
+ }
+ dbx_psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ if (LDSYMLEN(pst)) /* Otherwise it's a dummy */
+ {
+ /* Init stuff necessary for reading in symbols */
+ stabsread_init ();
+ buildsym_init ();
+ old_chain = make_cleanup (really_free_pendings, 0);
+ file_string_table_offset = FILE_STRING_OFFSET (pst);
+ symbol_size = SYMBOL_SIZE (pst);
+
+ /* Read in this file's symbols */
+ bfd_seek (pst->objfile->obfd, SYMBOL_OFFSET (pst), SEEK_SET);
+ read_ofile_symtab (pst);
+ sort_symtab_syms (pst->symtab);
+
+ 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;
+{
+ bfd *sym_bfd;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf (stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ if (LDSYMLEN(pst) || 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);
+ }
+
+ sym_bfd = pst->objfile->obfd;
+
+ next_symbol_text_func = dbx_next_symbol_text;
+
+ dbx_psymtab_to_symtab_1 (pst);
+
+ /* 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 (pst->objfile);
+
+ /* Finish up the debug error message. */
+ if (info_verbose)
+ printf_filtered ("done.\n");
+ }
+}
+
+/* Read in a defined section of a specific object file's symbols. */
+
+static void
+read_ofile_symtab (pst)
+ struct partial_symtab *pst;
+{
+ register char *namestring;
+ register struct internal_nlist *bufp;
+ unsigned char type;
+ unsigned max_symnum;
+ register bfd *abfd;
+ struct objfile *objfile;
+ int sym_offset; /* Offset to start of symbols to read */
+ int sym_size; /* Size of symbols to read */
+ CORE_ADDR text_offset; /* Start of text segment for symbols */
+ int text_size; /* Size of text segment for symbols */
+ struct section_offsets *section_offsets;
+
+ objfile = pst->objfile;
+ sym_offset = LDSYMOFF(pst);
+ sym_size = LDSYMLEN(pst);
+ text_offset = pst->textlow;
+ text_size = pst->texthigh - pst->textlow;
+ section_offsets = pst->section_offsets;
+
+ current_objfile = objfile;
+ subfile_stack = NULL;
+
+ stringtab_global = DBX_STRINGTAB (objfile);
+ last_source_file = NULL;
+
+ abfd = objfile->obfd;
+ symfile_bfd = objfile->obfd; /* Implicit param to next_text_symbol */
+ 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 (!processing_acc_compilation && sym_offset >= (int)symbol_size)
+ {
+ bfd_seek (symfile_bfd, sym_offset - symbol_size, SEEK_CUR);
+ fill_symbuf (abfd);
+ bufp = &symbuf[symbuf_idx++];
+ SWAP_SYMBOL (bufp, abfd);
+
+ SET_NAMESTRING ();
+
+ processing_gcc_compilation = 0;
+ if (bufp->n_type == N_TEXT)
+ {
+ if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 1;
+ else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 2;
+ }
+
+ /* Try to select a C++ demangling based on the compilation unit
+ producer. */
+
+ if (processing_gcc_compilation)
+ {
+ if (AUTO_DEMANGLING)
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+ }
+ }
+ 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. */
+ bfd_seek (symfile_bfd, sym_offset, SEEK_CUR);
+ processing_gcc_compilation = 0;
+ }
+
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (abfd);
+ bufp = &symbuf[symbuf_idx];
+ if (bufp->n_type != (unsigned char)N_SO)
+ error("First symbol in segment of executable not a source symbol");
+
+ max_symnum = sym_size / symbol_size;
+
+ for (symnum = 0;
+ symnum < max_symnum;
+ symnum++)
+ {
+ QUIT; /* Allow this to be interruptable */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf(abfd);
+ bufp = &symbuf[symbuf_idx++];
+ SWAP_SYMBOL (bufp, abfd);
+
+ type = bufp->n_type;
+
+ SET_NAMESTRING ();
+
+ if (type & N_STAB) {
+ process_one_symbol (type, bufp->n_desc, bufp->n_value,
+ namestring, section_offsets, objfile);
+ }
+ /* We skip checking for a new .o or -l file; that should never
+ happen in this routine. */
+ else if (type == N_TEXT)
+ {
+ /* 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. */
+
+ if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 1;
+ else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 2;
+
+ if (AUTO_DEMANGLING)
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+ }
+ 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. */
+ ;
+ }
+ }
+
+ current_objfile = NULL;
+
+ /* In a Solaris elf file, this variable, which comes from the
+ value of the N_SO symbol, will still be 0. Luckily, text_offset,
+ which comes from pst->textlow is correct. */
+ if (last_source_start_addr == 0)
+ last_source_start_addr = text_offset;
+
+ pst->symtab = end_symtab (text_offset + text_size, 0, 0, objfile,
+ SECT_OFF_TEXT);
+ end_stabs ();
+}
+
+
+/* This handles a single symbol from the symbol-file, building symbols
+ into a GDB symtab. It takes these arguments and an implicit argument.
+
+ TYPE is the type field of the ".stab" symbol entry.
+ DESC is the desc field of the ".stab" entry.
+ VALU is the value field of the ".stab" entry.
+ NAME is the symbol name, in our address space.
+ SECTION_OFFSETS is a set of amounts by which the sections of this object
+ file were relocated when it was loaded into memory.
+ All symbols that refer
+ to memory locations need to be offset by these amounts.
+ OBJFILE is the object file from which we are reading symbols.
+ It is used in end_symtab. */
+
+void
+process_one_symbol (type, desc, valu, name, section_offsets, objfile)
+ int type, desc;
+ CORE_ADDR valu;
+ char *name;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+#ifdef SUN_FIXED_LBRAC_BUG
+ /* If SUN_FIXED_LBRAC_BUG is defined, then it tells us whether we need
+ to correct the address of N_LBRAC's. If it is not defined, then
+ we never need to correct the addresses. */
+
+ /* This records the last pc address we've seen. We depend on there 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;
+ /* This remembers the address of the start of a function. It is used
+ because in Solaris 2, N_LBRAC, N_RBRAC, and N_SLINE entries are
+ relative to the current function's start address. On systems
+ other than Solaris 2, this just holds the SECT_OFF_TEXT value, and is
+ used to relocate these symbol types rather than SECTION_OFFSETS. */
+ static CORE_ADDR function_start_offset;
+
+ /* If this is nonzero, N_LBRAC, N_RBRAC, and N_SLINE entries are relative
+ to the function start address. */
+ int block_address_function_relative;
+
+ /* If this is nonzero, we've seen a non-gcc N_OPT symbol for this source
+ file. Used to detect the SunPRO solaris compiler. */
+ static int n_opt_found;
+
+ /* The stab type used for the definition of the last function.
+ N_STSYM or N_GSYM for SunOS4 acc; N_FUN for other compilers. */
+ static int function_stab_type = 0;
+
+ /* This is true for Solaris (and all other stabs-in-elf systems, hopefully,
+ since it would be silly to do things differently from Solaris), and
+ false for SunOS4 and other a.out file formats. */
+ block_address_function_relative =
+ 0 == strncmp (bfd_get_target (objfile->obfd), "elf", 3);
+
+ if (!block_address_function_relative)
+ /* N_LBRAC, N_RBRAC and N_SLINE entries are not relative to the
+ function start address, so just use the text offset. */
+ function_start_offset = ANOFFSET (section_offsets, SECT_OFF_TEXT);
+
+ /* Something is wrong if we see real data before
+ seeing a source file name. */
+
+ if (last_source_file == NULL && type != (unsigned char)N_SO)
+ {
+ /* Ignore any symbols which appear before an N_SO symbol. Currently
+ no one puts symbols there, but we should deal gracefully with the
+ case. A complain()t might be in order (if !IGNORE_SYMBOL (type)),
+ but this should not be an error (). */
+ return;
+ }
+
+ switch (type)
+ {
+ case N_FUN:
+ case N_FNAME:
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ goto define_a_symbol;
+
+ case N_LBRAC:
+ /* This "symbol" just indicates the start of an inner lexical
+ context within a function. */
+
+#if defined(BLOCK_ADDRESS_ABSOLUTE)
+ /* Relocate for dynamic loading (?). */
+ valu += function_start_offset;
+#else
+ if (block_address_function_relative)
+ /* Relocate for Sun ELF acc fn-relative syms. */
+ valu += function_start_offset;
+ else
+ /* 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
+
+#ifdef SUN_FIXED_LBRAC_BUG
+ if (!SUN_FIXED_LBRAC_BUG && valu < last_pc_address) {
+ /* Patch current LBRAC pc value to match last handy pc value */
+ complain (&lbrac_complaint);
+ valu = last_pc_address;
+ }
+#endif
+ new = push_context (desc, valu);
+ 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)
+ /* Relocate for dynamic loading (?). */
+ valu += function_start_offset;
+#else
+ if (block_address_function_relative)
+ /* Relocate for Sun ELF acc fn-relative syms. */
+ valu += function_start_offset;
+ else
+ /* 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 = pop_context();
+ if (desc != new->depth)
+ complain (&lbrac_mismatch_complaint, 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
+ or the GCC2_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);
+ new->start_addr = valu;
+ }
+ /* Make a block for the local symbols within. */
+ finish_block (0, &local_symbols, new->old_blocks,
+ new->start_addr, valu, objfile);
+ }
+ 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:
+ case N_FN_SEQ:
+ /* This kind of symbol indicates the start of an object file. */
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ 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. */
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+
+ n_opt_found = 0;
+
+#ifdef 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)
+ {
+ /* Check if previous symbol was also an N_SO (with some
+ sanity checks). If so, that one was actually the directory
+ name, and the current one is the real file name.
+ Patch things up. */
+ if (previous_stab_code == (unsigned char) N_SO)
+ {
+ patch_subfile_names (current_subfile, name);
+ break; /* Ignore repeated SOs */
+ }
+ end_symtab (valu, 0, 0, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+ }
+ start_stabs ();
+ 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.) */
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ start_subfile (name, current_subfile->dirname);
+ break;
+
+ case N_BINCL:
+ push_subfile ();
+ add_new_header_file (name, valu);
+ start_subfile (name, current_subfile->dirname);
+ break;
+
+ case N_EINCL:
+ start_subfile (pop_subfile (), current_subfile->dirname);
+ 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. */
+ /* Relocate for dynamic loading and for ELF acc fn-relative syms. */
+ valu += function_start_offset;
+#ifdef SUN_FIXED_LBRAC_BUG
+ last_pc_address = valu; /* Save for SunOS bug circumcision */
+#endif
+ record_line (current_subfile, desc, valu);
+ break;
+
+ case N_BCOMM:
+ common_block_start (name, objfile);
+ break;
+
+ case N_ECOMM:
+ common_block_end (objfile);
+ break;
+
+ /* The following symbol types need to have the appropriate offset added
+ to their value; then we process symbol definitions in the name. */
+
+ case N_STSYM: /* Static symbol in data seg */
+ case N_LCSYM: /* Static symbol in BSS seg */
+ case N_ROSYM: /* Static symbol in Read-only data seg */
+ /* HORRID HACK DEPT. However, it's Sun's furgin' fault.
+ Solaris2's stabs-in-elf makes *most* symbols relative
+ but leaves a few absolute (at least for Solaris 2.1 and version
+ 2.0.1 of the SunPRO compiler). N_STSYM and friends sit on the fence.
+ .stab "foo:S...",N_STSYM is absolute (ld relocates it)
+ .stab "foo:V...",N_STSYM is relative (section base subtracted).
+ This leaves us no choice but to search for the 'S' or 'V'...
+ (or pass the whole section_offsets stuff down ONE MORE function
+ call level, which we really don't want to do). */
+ {
+ char *p;
+ p = strchr (name, ':');
+ if (p != 0 && p[1] == 'S')
+ {
+ /* The linker relocated it. There used to be a kludge here
+ to add the text offset, but that will break if we ever
+ start using the text offset (currently it is always zero). */
+ goto define_a_symbol;
+ }
+ /* Since it's not the kludge case, re-dispatch to the right handler. */
+ switch (type) {
+ case N_STSYM: goto case_N_STSYM;
+ case N_LCSYM: goto case_N_LCSYM;
+ case N_ROSYM: goto case_N_ROSYM;
+ default: abort();
+ }
+ }
+
+ case_N_STSYM: /* Static symbol in data seg */
+ case N_DSLINE: /* Source line number, data seg */
+ valu += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ goto define_a_symbol;
+
+ case_N_LCSYM: /* Static symbol in BSS seg */
+ case N_BSLINE: /* Source line number, bss seg */
+ /* N_BROWS: overlaps with N_BSLINE */
+ valu += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ goto define_a_symbol;
+
+ case_N_ROSYM: /* Static symbol in Read-only data seg */
+ valu += ANOFFSET (section_offsets, SECT_OFF_RODATA);
+ goto define_a_symbol;
+
+ case N_ENTRY: /* Alternate entry point */
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ goto define_a_symbol;
+
+ /* The following symbol types we don't know how to process. Handle
+ them in a "default" way, but complain to people who care. */
+ default:
+ case N_CATCH: /* Exception handler catcher */
+ case N_EHDECL: /* Exception handler name */
+ case N_PC: /* Global symbol in Pascal */
+ case N_M2C: /* Modula-2 compilation unit */
+ /* N_MOD2: overlaps with N_EHDECL */
+ case N_SCOPE: /* Modula-2 scope information */
+ case N_ECOML: /* End common (local name) */
+ case N_NBTEXT: /* Gould Non-Base-Register symbols??? */
+ case N_NBDATA:
+ case N_NBBSS:
+ case N_NBSTS:
+ case N_NBLCS:
+ complain (&unknown_symtype_complaint,
+ local_hex_string((unsigned long) type));
+ /* FALLTHROUGH */
+
+ /* The following symbol types don't need the address field relocated,
+ since it is either unused, or is absolute. */
+ define_a_symbol:
+ case N_GSYM: /* Global variable */
+ case N_NSYMS: /* Number of symbols (ultrix) */
+ case N_NOMAP: /* No map? (ultrix) */
+ case N_RSYM: /* Register variable */
+ case N_DEFD: /* Modula-2 GNU module dependency */
+ case N_SSYM: /* Struct or union element */
+ case N_LSYM: /* Local symbol in stack */
+ case N_PSYM: /* Parameter variable */
+ case N_LENG: /* Length of preceding symbol type */
+ if (name)
+ {
+ int deftype;
+ char *colon_pos = strchr (name, ':');
+ if (colon_pos == NULL)
+ deftype = '\0';
+ else
+ deftype = colon_pos[1];
+
+ switch (deftype)
+ {
+ case 'f':
+ case 'F':
+ function_stab_type = type;
+
+#ifdef SUN_FIXED_LBRAC_BUG
+ /* The Sun acc compiler, under SunOS4, puts out
+ functions with N_GSYM or N_STSYM. The problem is
+ that the address of the symbol is no good (for N_GSYM
+ it doesn't even attept an address; for N_STSYM it
+ puts out an address but then it gets relocated
+ relative to the data segment, not the text segment).
+ Currently we can't fix this up later as we do for
+ some types of symbol in scan_file_globals.
+ Fortunately we do have a way of finding the address -
+ we know that the value in last_pc_address is either
+ the one we want (if we're dealing with the first
+ function in an object file), or somewhere in the
+ previous function. This means that we can use the
+ minimal symbol table to get the address. */
+
+ /* On solaris up to 2.2, the N_FUN stab gets relocated.
+ On Solaris 2.3, ld no longer relocates stabs (which
+ is good), and the N_FUN's value is now always zero.
+ The following code can't deal with this, because
+ last_pc_address depends on getting the address from a
+ N_SLINE or some such and in Solaris those are function
+ relative. Best fix is probably to create a Ttext.text symbol
+ and handle this like Ddata.data and so on. */
+
+ if (type == N_GSYM || type == N_STSYM)
+ {
+ struct minimal_symbol *m;
+ int l = colon_pos - name;
+
+ m = lookup_minimal_symbol_by_pc (last_pc_address);
+ if (m && STREQN (SYMBOL_NAME (m), name, l))
+ /* last_pc_address was in this function */
+ valu = SYMBOL_VALUE (m);
+ else if (m && STREQN (SYMBOL_NAME (m+1), name, l))
+ /* last_pc_address was in last function */
+ valu = SYMBOL_VALUE (m+1);
+ else
+ /* Not found - use last_pc_address (for finish_block) */
+ valu = last_pc_address;
+ }
+
+ last_pc_address = valu; /* Save for SunOS bug circumcision */
+#endif
+
+ if (block_address_function_relative)
+ /* For Solaris 2.0 compilers, the block addresses and
+ N_SLINE's are relative to the start of the
+ function. On normal systems, and when using gcc on
+ Solaris 2.0, these addresses are just absolute, or
+ relative to the N_SO, depending on
+ BLOCK_ADDRESS_ABSOLUTE. */
+ function_start_offset = valu;
+
+ within_function = 1;
+ if (context_stack_depth > 0)
+ {
+ new = pop_context ();
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, valu, objfile);
+ }
+ /* Stack must be empty now. */
+ if (context_stack_depth != 0)
+ complain (&lbrac_unmatched_complaint, symnum);
+
+ new = push_context (0, valu);
+ new->name = define_symbol (valu, name, desc, type, objfile);
+ break;
+
+ default:
+ define_symbol (valu, name, desc, type, objfile);
+ break;
+ }
+ }
+ break;
+
+ /* We use N_OPT to carry the gcc2_compiled flag. Sun uses it
+ for a bunch of other flags, too. Someday we may parse their
+ flags; for now we ignore theirs and hope they'll ignore ours. */
+ case N_OPT: /* Solaris 2: Compiler options */
+ if (name)
+ {
+ if (STREQ (name, GCC2_COMPILED_FLAG_SYMBOL))
+ {
+ processing_gcc_compilation = 2;
+#if 1 /* Works, but is experimental. -fnf */
+ if (AUTO_DEMANGLING)
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+#endif
+ }
+ else
+ n_opt_found = 1;
+ }
+ break;
+
+ /* The following symbol types can be ignored. */
+ case N_OBJ: /* Solaris 2: Object file dir and name */
+ /* N_UNDF: Solaris 2: file separator mark */
+ /* N_UNDF: -- we will never encounter it, since we only process one
+ file's symbols at once. */
+ case N_ENDM: /* Solaris 2: End of module */
+ case N_MAIN: /* Name of main routine. */
+ break;
+ }
+
+ previous_stab_code = type;
+}
+
+/* FIXME: The only difference between this and elfstab_build_psymtabs is
+ the call to install_minimal_symbols for elf. If the differences are
+ really that small, the code should be shared. */
+
+/* Scan and build partial symbols for an coff symbol file.
+ The coff file has already been processed to get its minimal symbols.
+
+ This routine is the equivalent of dbx_symfile_init and dbx_symfile_read
+ rolled into one.
+
+ OBJFILE is the object file we are reading symbols from.
+ ADDR is the address relative to which the symbols 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).
+ STABOFFSET and STABSIZE define the location in OBJFILE where the .stab
+ section exists.
+ STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
+ .stabstr section exists.
+
+ This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
+ adjusted for coff details. */
+
+void
+coffstab_build_psymtabs (objfile, section_offsets, mainline,
+ staboffset, stabsize,
+ stabstroffset, stabstrsize)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+ file_ptr staboffset;
+ unsigned int stabsize;
+ file_ptr stabstroffset;
+ unsigned int stabstrsize;
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ struct dbx_symfile_info *info;
+
+ /* There is already a dbx_symfile_info allocated by our caller.
+ It might even contain some info from the coff symtab to help us. */
+ info = (struct dbx_symfile_info *) objfile->sym_stab_info;
+
+ DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!DBX_TEXT_SECT (objfile))
+ error ("Can't find .text section in symbol file");
+
+#define COFF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
+ DBX_SYMBOL_SIZE (objfile) = COFF_STABS_SYMBOL_SIZE;
+ DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
+ DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
+ DBX_SYMTAB_OFFSET (objfile) = staboffset;
+
+ if (stabstrsize > bfd_get_size (sym_bfd))
+ error ("ridiculous string table size: %d bytes", stabstrsize);
+ DBX_STRINGTAB (objfile) = (char *)
+ obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, 1, sym_bfd);
+ if (val != stabstrsize)
+ perror_with_name (name);
+
+ stabsread_new_init ();
+ buildsym_new_init ();
+ free_header_files ();
+ init_header_files ();
+
+ processing_acc_compilation = 1;
+
+ /* In a coff file, we've already installed the minimal symbols that came
+ from the coff (non-stab) symbol table, so always act like an
+ incremental load here. */
+ dbx_symfile_read (objfile, section_offsets, 0);
+}
+
+/* Scan and build partial symbols for an ELF symbol file.
+ This ELF file has already been processed to get its minimal symbols,
+ and any DWARF symbols that were in it.
+
+ This routine is the equivalent of dbx_symfile_init and dbx_symfile_read
+ rolled into one.
+
+ OBJFILE is the object file we are reading symbols from.
+ ADDR is the address relative to which the symbols 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).
+ STABOFFSET and STABSIZE define the location in OBJFILE where the .stab
+ section exists.
+ STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
+ .stabstr section exists.
+
+ This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
+ adjusted for elf details. */
+
+void
+elfstab_build_psymtabs (objfile, section_offsets, mainline,
+ staboffset, stabsize,
+ stabstroffset, stabstrsize)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+ file_ptr staboffset;
+ unsigned int stabsize;
+ file_ptr stabstroffset;
+ unsigned int stabstrsize;
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ struct dbx_symfile_info *info;
+
+ /* There is already a dbx_symfile_info allocated by our caller.
+ It might even contain some info from the ELF symtab to help us. */
+ info = (struct dbx_symfile_info *) objfile->sym_stab_info;
+
+ DBX_TEXT_SECT (objfile) = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!DBX_TEXT_SECT (objfile))
+ error ("Can't find .text section in symbol file");
+
+#define ELF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
+ DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE;
+ DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
+ DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
+ DBX_SYMTAB_OFFSET (objfile) = staboffset;
+
+ if (stabstrsize > bfd_get_size (sym_bfd))
+ error ("ridiculous string table size: %d bytes", stabstrsize);
+ DBX_STRINGTAB (objfile) = (char *)
+ obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, 1, sym_bfd);
+ if (val != stabstrsize)
+ perror_with_name (name);
+
+ stabsread_new_init ();
+ buildsym_new_init ();
+ free_header_files ();
+ init_header_files ();
+ install_minimal_symbols (objfile);
+
+ processing_acc_compilation = 1;
+
+ /* In an elf file, we've already installed the minimal symbols that came
+ from the elf (non-stab) symbol table, so always act like an
+ incremental load here. */
+ dbx_symfile_read (objfile, section_offsets, 0);
+}
+
+/* Scan and build partial symbols for a PA symbol file.
+ This PA file has already been processed to get its minimal symbols.
+
+ OBJFILE is the object file we are reading symbols from.
+ ADDR is the address relative to which the symbols 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
+pastab_build_psymtabs (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ free_header_files ();
+ init_header_files ();
+
+ /* In a PA file, we've already installed the minimal symbols that came
+ from the PA (non-stab) symbol table, so always act like an
+ incremental load here. */
+
+ dbx_symfile_read (objfile, section_offsets, mainline);
+}
+
+/* Parse the user's idea of an offset for dynamic linking, into our idea
+ of how to represent it for fast symbol reading. */
+
+static struct section_offsets *
+dbx_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets) +
+ sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+/* Register our willingness to decode symbols for SunOS and a.out and
+ NetBSD and b.out files handled by BFD... */
+static struct sym_fns sunos_sym_fns =
+{
+ "sunOs", /* sym_name: name or name prefix of BFD target type */
+ 6, /* sym_namelen: number of significant sym_name chars */
+ dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ dbx_symfile_read, /* sym_read: read a symbol file into symtab */
+ dbx_symfile_finish, /* sym_finish: finished with file, cleanup */
+ dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+static struct sym_fns aout_sym_fns =
+{
+ "a.out", /* sym_name: name or name prefix of BFD target type */
+ 5, /* sym_namelen: number of significant sym_name chars */
+ dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ dbx_symfile_read, /* sym_read: read a symbol file into symtab */
+ dbx_symfile_finish, /* sym_finish: finished with file, cleanup */
+ dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+static struct sym_fns bout_sym_fns =
+{
+ "b.out", /* sym_name: name or name prefix of BFD target type */
+ 5, /* sym_namelen: number of significant sym_name chars */
+ dbx_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ dbx_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ dbx_symfile_read, /* sym_read: read a symbol file into symtab */
+ dbx_symfile_finish, /* sym_finish: finished with file, cleanup */
+ dbx_symfile_offsets, /* sym_offsets: parse user's offsets to internal form */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_dbxread ()
+{
+ add_symtab_fns(&sunos_sym_fns);
+ add_symtab_fns(&aout_sym_fns);
+ add_symtab_fns(&bout_sym_fns);
+}
diff --git a/gnu/usr.bin/gdb/gdb/dcache.c b/gnu/usr.bin/gdb/gdb/dcache.c
new file mode 100644
index 000000000000..aaa01d0fe227
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/dcache.c
@@ -0,0 +1,236 @@
+/* Caching code. Typically used by remote back ends for
+ caching remote memory.
+
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "dcache.h"
+#include "gdbcmd.h"
+
+extern int insque();
+extern int remque();
+
+int remote_dcache = 0;
+
+/* The data cache records all the data read from the remote machine
+ since the last time it stopped.
+
+ Each cache block holds LINE_SIZE bytes of data
+ starting at a multiple-of-LINE_SIZE address. */
+
+#define LINE_SIZE_MASK ((LINE_SIZE - 1)) /* eg 7*2+1= 111*/
+#define XFORM(x) (((x) & LINE_SIZE_MASK) >> 2)
+
+/* Free all the data cache blocks, thus discarding all cached data. */
+void
+dcache_flush (dcache)
+ DCACHE *dcache;
+{
+ register struct dcache_block *db;
+
+ if (remote_dcache > 0)
+ while ((db = dcache->dcache_valid.next) != &dcache->dcache_valid)
+ {
+ remque (db);
+ insque (db, &dcache->dcache_free);
+ }
+
+ return;
+}
+
+/*
+ * If addr is present in the dcache, return the address of the block
+ * containing it.
+ */
+static
+struct dcache_block *
+dcache_hit (dcache, addr)
+ DCACHE *dcache;
+ unsigned int addr;
+{
+ register struct dcache_block *db;
+
+ if (addr & 3
+ || remote_dcache == 0)
+ abort ();
+
+ /* Search all cache blocks for one that is at this address. */
+ db = dcache->dcache_valid.next;
+ while (db != &dcache->dcache_valid)
+ {
+ if ((addr & ~LINE_SIZE_MASK) == 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
+ || remote_dcache == 0)
+ abort ();
+ return (db->data[XFORM (addr)]);
+}
+
+/* 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 memory retrieval is
+ interrupted (which used to put garbage blocks in the valid
+ list...). */
+static
+struct dcache_block *
+dcache_alloc (dcache)
+ DCACHE *dcache;
+{
+ register struct dcache_block *db;
+
+ if (remote_dcache == 0)
+ abort();
+
+ if ((db = dcache->dcache_free.next) == &dcache->dcache_free)
+ {
+ /* If we can't get one from the free list, take last valid and put
+ it on the free list. */
+ db = dcache->dcache_valid.last;
+ remque (db);
+ insque (db, &dcache->dcache_free);
+ }
+
+ remque (db);
+ insque (db, &dcache->dcache_valid);
+ return (db);
+}
+
+/* Using the data cache DCACHE return the contents of the word at
+ address ADDR in the remote machine. */
+int
+dcache_fetch (dcache, addr)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+{
+ register struct dcache_block *db;
+
+ if (remote_dcache == 0)
+ {
+ int i;
+
+ (*dcache->read_memory) (addr, (unsigned char *) &i, 4);
+ return(i);
+ }
+
+ db = dcache_hit (dcache, addr);
+ if (db == 0)
+ {
+ db = dcache_alloc (dcache);
+ immediate_quit++;
+ (*dcache->read_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
+ immediate_quit--;
+ db->addr = addr & ~LINE_SIZE_MASK;
+ remque (db); /* Off the free list */
+ insque (db, &dcache->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. */
+void
+dcache_poke (dcache, addr, data)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+ int data;
+{
+ register struct dcache_block *db;
+
+ if (remote_dcache == 0)
+ {
+ (*dcache->write_memory) (addr, (unsigned char *) &data, 4);
+ return;
+ }
+
+ /* First make sure the word is IN the cache. DB is its cache block. */
+ db = dcache_hit (dcache, addr);
+ if (db == 0)
+ {
+ db = dcache_alloc (dcache);
+ immediate_quit++;
+ (*dcache->write_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
+ immediate_quit--;
+ db->addr = addr & ~LINE_SIZE_MASK;
+ remque (db); /* Off the free list */
+ insque (db, &dcache->dcache_valid); /* On the valid list */
+ }
+
+ /* Modify the word in the cache. */
+ db->data[XFORM (addr)] = data;
+
+ /* Send the changed word. */
+ immediate_quit++;
+ (*dcache->write_memory) (addr, (unsigned char *) &data, 4);
+ immediate_quit--;
+}
+
+/* Initialize the data cache. */
+DCACHE *
+dcache_init (reading, writing)
+ memxferfunc reading;
+ memxferfunc writing;
+{
+ register i;
+ register struct dcache_block *db;
+ DCACHE *dcache;
+
+ dcache = (DCACHE *) xmalloc (sizeof (*dcache));
+ dcache->read_memory = reading;
+ dcache->write_memory = writing;
+ dcache->the_cache = (struct dcache_block *)
+ xmalloc (sizeof (*dcache->the_cache) * DCACHE_SIZE);
+
+ dcache->dcache_free.next = dcache->dcache_free.last = &dcache->dcache_free;
+ dcache->dcache_valid.next = dcache->dcache_valid.last = &dcache->dcache_valid;
+ for (db = dcache->the_cache, i = 0; i < DCACHE_SIZE; i++, db++)
+ insque (db, &dcache->dcache_free);
+
+ return(dcache);
+}
+
+void
+_initialitize_dcache ()
+{
+ add_show_from_set
+ (add_set_cmd ("remotecache", class_support, var_boolean,
+ (char *) &remote_dcache,
+ "\
+Set cache use for remote targets.\n\
+When on, use data caching for remote targets. For many remote targets\n\
+this option can offer better throughput for reading target memory.\n\
+Unfortunately, gdb does not currently know anything about volatile\n\
+registers and thus data caching will produce incorrect results with\n\
+volatile registers are in use. By default, this option is off.",
+ &setlist),
+ &showlist);
+}
diff --git a/gnu/usr.bin/gdb/gdb/dcache.h b/gnu/usr.bin/gdb/gdb/dcache.h
new file mode 100644
index 000000000000..bfc0dd7a1e3c
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/dcache.h
@@ -0,0 +1,83 @@
+/* Declarations for caching. Typically used by remote back ends for
+ caching remote memory.
+
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef DCACHE_H
+#define DCACHE_H
+
+/* 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. */
+
+#define LINE_SIZE_POWER (4)
+/* eg 1<<3 == 8 */
+#define LINE_SIZE (1 << LINE_SIZE_POWER)
+/* Number of cache blocks */
+#define DCACHE_SIZE (64)
+
+struct dcache_block
+{
+ struct dcache_block *next, *last;
+ unsigned int addr; /* Address for which data is recorded. */
+ int data[LINE_SIZE / sizeof (int)];
+};
+
+typedef int (*memxferfunc) PARAMS((CORE_ADDR memaddr,
+ unsigned char *myaddr,
+ int len));
+
+typedef struct {
+ /* Function to actually read the target memory. */
+ memxferfunc read_memory;
+
+ /* Function to actually write the target memory */
+ memxferfunc write_memory;
+
+ /* free list */
+ struct dcache_block dcache_free;
+
+ /* in use list */
+ struct dcache_block dcache_valid;
+
+ /* The cache itself. */
+ struct dcache_block *the_cache;
+
+} DCACHE;
+
+/* Using the data cache DCACHE return the contents of the word at
+ address ADDR in the remote machine. */
+int dcache_fetch PARAMS((DCACHE *dcache, CORE_ADDR addr));
+
+/* Flush DCACHE. */
+void dcache_flush PARAMS((DCACHE *dcache));
+
+/* Initialize DCACHE. */
+DCACHE *dcache_init PARAMS((memxferfunc reading, memxferfunc writing));
+
+/* Write the word at ADDR both in the data cache and in the remote machine. */
+void dcache_poke PARAMS((DCACHE *dcache, CORE_ADDR addr, int data));
+
+#endif /* DCACHE_H */
diff --git a/gnu/usr.bin/gdb/gdb/defs.h b/gnu/usr.bin/gdb/gdb/defs.h
new file mode 100644
index 000000000000..f65d56ac5878
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/defs.h
@@ -0,0 +1,901 @@
+/* Basic, host-specific, and target-specific definitions for GDB.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (DEFS_H)
+#define DEFS_H 1
+
+#include <stdio.h>
+
+/* First include ansidecl.h so we can use the various macro definitions
+ here and in all subsequent file inclusions. */
+
+#include "ansidecl.h"
+
+/* An address in the program being debugged. Host byte order. */
+#ifndef CORE_ADDR_TYPE
+typedef unsigned int CORE_ADDR;
+#else
+typedef CORE_ADDR_TYPE CORE_ADDR;
+#endif
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+/* Gdb does *lots* of string compares. Use macros to speed them up by
+ avoiding function calls if the first characters are not the same. */
+
+#define STRCMP(a,b) (*(a) == *(b) ? strcmp ((a), (b)) : (int)*(a) - (int)*(b))
+#define STREQ(a,b) (*(a) == *(b) ? !strcmp ((a), (b)) : 0)
+#define STREQN(a,b,c) (*(a) == *(b) ? !strncmp ((a), (b), (c)) : 0)
+
+/* The character GNU 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 */
+
+#include <errno.h> /* System call error return status */
+
+extern int quit_flag;
+extern int immediate_quit;
+extern int sevenbit_strings;
+
+extern void
+quit PARAMS ((void));
+
+#define QUIT { if (quit_flag) quit (); }
+
+/* Command classes are top-level categories into which commands are broken
+ down for "help" purposes.
+ Notes on classes: class_alias is for alias commands which are not
+ abbreviations of the original command. class-pseudo is for commands
+ which are not really commands nor help topics ("stop"). */
+
+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, class_maintenance,
+ class_pseudo
+};
+
+/* Languages represented in the symbol table and elsewhere.
+ This should probably be in language.h, but since enum's can't
+ be forward declared to satisfy opaque references before their
+ actual definition, needs to be here. */
+
+enum language
+{
+ language_unknown, /* Language not known */
+ language_auto, /* Placeholder for automatic setting */
+ language_c, /* C */
+ language_cplus, /* C++ */
+ language_chill, /* Chill */
+ language_m2 /* Modula-2 */
+};
+
+/* 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) PARAMS ((PTR));
+ PTR arg;
+};
+
+/* From blockframe.c */
+
+extern int
+inside_entry_func PARAMS ((CORE_ADDR));
+
+extern int
+inside_entry_file PARAMS ((CORE_ADDR addr));
+
+extern int
+inside_main_func PARAMS ((CORE_ADDR pc));
+
+/* From ch-lang.c, for the moment. (FIXME) */
+
+extern char *
+chill_demangle PARAMS ((const char *));
+
+/* From libiberty.a */
+
+extern char *
+cplus_demangle PARAMS ((const char *, int));
+
+extern char *
+cplus_mangle_opname PARAMS ((char *, int));
+
+/* From libmmalloc.a (memory mapped malloc library) */
+
+extern PTR
+mmalloc_attach PARAMS ((int, PTR));
+
+extern PTR
+mmalloc_detach PARAMS ((PTR));
+
+extern PTR
+mmalloc PARAMS ((PTR, long));
+
+extern PTR
+mrealloc PARAMS ((PTR, PTR, long));
+
+extern void
+mfree PARAMS ((PTR, PTR));
+
+extern int
+mmalloc_setkey PARAMS ((PTR, int, PTR));
+
+extern PTR
+mmalloc_getkey PARAMS ((PTR, int));
+
+/* From utils.c */
+
+extern int
+strcmp_iw PARAMS ((const char *, const char *));
+
+extern char *
+safe_strerror PARAMS ((int));
+
+extern char *
+safe_strsignal PARAMS ((int));
+
+extern void
+init_malloc PARAMS ((void *));
+
+extern void
+request_quit PARAMS ((int));
+
+extern void
+do_cleanups PARAMS ((struct cleanup *));
+
+extern void
+discard_cleanups PARAMS ((struct cleanup *));
+
+/* The bare make_cleanup function is one of those rare beasts that
+ takes almost any type of function as the first arg and anything that
+ will fit in a "void *" as the second arg.
+
+ Should be, once all calls and called-functions are cleaned up:
+extern struct cleanup *
+make_cleanup PARAMS ((void (*function) (void *), void *));
+
+ Until then, lint and/or various type-checking compiler options will
+ complain about make_cleanup calls. It'd be wrong to just cast things,
+ since the type actually passed when the function is called would be
+ wrong. */
+
+extern struct cleanup *
+make_cleanup ();
+
+extern struct cleanup *
+save_cleanups PARAMS ((void));
+
+extern void
+restore_cleanups PARAMS ((struct cleanup *));
+
+extern void
+free_current_contents PARAMS ((char **));
+
+extern void
+null_cleanup PARAMS ((char **));
+
+extern int
+myread PARAMS ((int, char *, int));
+
+extern int
+query ();
+
+extern void
+begin_line PARAMS ((void));
+
+extern void
+wrap_here PARAMS ((char *));
+
+extern void
+reinitialize_more_filter PARAMS ((void));
+
+extern int
+print_insn PARAMS ((CORE_ADDR, FILE *));
+
+extern void
+fputs_filtered PARAMS ((const char *, FILE *));
+
+extern void
+puts_filtered PARAMS ((char *));
+
+extern void
+vprintf_filtered ();
+
+extern void
+vfprintf_filtered ();
+
+extern void
+fprintf_filtered ();
+
+extern void
+fprintfi_filtered ();
+
+extern void
+printf_filtered ();
+
+extern void
+printfi_filtered ();
+
+extern void
+print_spaces PARAMS ((int, FILE *));
+
+extern void
+print_spaces_filtered PARAMS ((int, FILE *));
+
+extern char *
+n_spaces PARAMS ((int));
+
+extern void
+gdb_printchar PARAMS ((int, FILE *, int));
+
+extern void
+fprintf_symbol_filtered PARAMS ((FILE *, char *, enum language, int));
+
+extern void
+perror_with_name PARAMS ((char *));
+
+extern void
+print_sys_errmsg PARAMS ((char *, int));
+
+/* From regex.c or libc. BSD 4.4 declares this with the argument type as
+ "const char *" in unistd.h, so we can't declare the argument
+ as "char *". */
+
+extern char *
+re_comp PARAMS ((const char *));
+
+/* From symfile.c */
+
+extern void
+symbol_file_command PARAMS ((char *, int));
+
+/* From main.c */
+
+extern char *
+skip_quoted PARAMS ((char *));
+
+extern char *
+gdb_readline PARAMS ((char *));
+
+extern char *
+command_line_input PARAMS ((char *, int));
+
+extern void
+print_prompt PARAMS ((void));
+
+extern int
+batch_mode PARAMS ((void));
+
+extern int
+input_from_terminal_p PARAMS ((void));
+
+/* From printcmd.c */
+
+extern void
+set_next_address PARAMS ((CORE_ADDR));
+
+extern void
+print_address_symbolic PARAMS ((CORE_ADDR, FILE *, int, char *));
+
+extern void
+print_address PARAMS ((CORE_ADDR, FILE *));
+
+/* From source.c */
+
+extern int
+openp PARAMS ((char *, int, char *, int, int, char **));
+
+extern void
+mod_path PARAMS ((char *, char **));
+
+extern void
+directory_command PARAMS ((char *, int));
+
+extern void
+init_source_path PARAMS ((void));
+
+/* From findvar.c */
+
+extern int
+read_relative_register_raw_bytes PARAMS ((int, char *));
+
+/* From readline (but not in any readline .h files). */
+
+extern char *
+tilde_expand PARAMS ((char *));
+
+/* 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 PARAMS ((void));
+
+extern void
+free_command_lines PARAMS ((struct command_line **));
+
+/* String containing the current directory (what getwd would return). */
+
+extern char *current_directory;
+
+/* Default radixes for input and output. Only some values supported. */
+extern unsigned input_radix;
+extern unsigned output_radix;
+
+/* Possibilities for prettyprint parameters to routines which print
+ things. Like enum language, this should be in value.h, but needs
+ to be here for the same reason. FIXME: If we can eliminate this
+ as an arg to LA_VAL_PRINT, then we can probably move it back to
+ value.h. */
+
+enum val_prettyprint
+{
+ Val_no_prettyprint = 0,
+ Val_prettyprint,
+ /* Use the default setting which the user has specified. */
+ Val_pretty_default
+};
+
+
+/* Host machine definition. This will be a symlink to one of the
+ xm-*.h files, built by the `configure' script. */
+
+#include "xm.h"
+
+/* Native machine support. This will be a symlink to one of the
+ nm-*.h files, built by the `configure' script. */
+
+#include "nm.h"
+
+/* If the xm.h file did not define the mode string used to open the
+ files, assume that binary files are opened the same way as text
+ files */
+#ifndef FOPEN_RB
+#include "fopen-same.h"
+#endif
+
+/*
+ * 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 const
+#ifndef __STDC__
+# ifdef __GNUC__
+# define const __const__
+# else
+# define const /*nothing*/
+# endif /* GNUC */
+#endif /* STDC */
+#endif /* const */
+
+#ifndef volatile
+#ifndef __STDC__
+# ifdef __GNUC__
+# define volatile __volatile__
+# else
+# define volatile /*nothing*/
+# endif /* GNUC */
+#endif /* STDC */
+#endif /* volatile */
+
+#if 1
+#define NORETURN /*nothing*/
+#else /* not 1 */
+/* FIXME: This is bogus. Having "volatile void" mean a function doesn't
+ return is a gcc extension and should be based on #ifdef __GNUC__.
+ Also, as of Sep 93 I'm told gcc is changing the syntax for ansi
+ reasons (so declaring exit here as "volatile void" and as "void" in
+ a system header loses). Using the new "__attributes__ ((noreturn));"
+ syntax would lose for old versions of gcc; using
+ typedef void exit_fn_type PARAMS ((int));
+ volatile exit_fn_type exit;
+ would win. */
+/* Some compilers (many AT&T SVR4 compilers for instance), do not accept
+ declarations of functions that never return (exit for instance) as
+ "volatile void". For such compilers "NORETURN" can be defined away
+ to keep them happy */
+
+#ifndef NORETURN
+# ifdef __lucid
+# define NORETURN /*nothing*/
+# else
+# define NORETURN volatile
+# endif
+#endif
+#endif /* not 1 */
+
+/* Defaults for system-wide constants (if not defined by xm.h, we fake it). */
+
+#if !defined (UINT_MAX)
+#define UINT_MAX ((unsigned int)(~0)) /* 0xFFFFFFFF for 32-bits */
+#endif
+
+#if !defined (INT_MAX)
+#define INT_MAX ((int)(UINT_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */
+#endif
+
+#if !defined (INT_MIN)
+#define INT_MIN (-INT_MAX - 1) /* 0x80000000 for 32-bits */
+#endif
+
+#if !defined (ULONG_MAX)
+#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF for 32-bits */
+#endif
+
+#if !defined (LONG_MAX)
+#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */
+#endif
+
+/* Number of bits in a char or unsigned char for the target machine.
+ Just like CHAR_BIT in <limits.h> but describes the target machine. */
+#if !defined (TARGET_CHAR_BIT)
+#define TARGET_CHAR_BIT 8
+#endif
+
+/* Number of bits in a short or unsigned short for the target machine. */
+#if !defined (TARGET_SHORT_BIT)
+#define TARGET_SHORT_BIT (2 * TARGET_CHAR_BIT)
+#endif
+
+/* Number of bits in an int or unsigned int for the target machine. */
+#if !defined (TARGET_INT_BIT)
+#define TARGET_INT_BIT (4 * TARGET_CHAR_BIT)
+#endif
+
+/* Number of bits in a long or unsigned long for the target machine. */
+#if !defined (TARGET_LONG_BIT)
+#define TARGET_LONG_BIT (4 * TARGET_CHAR_BIT)
+#endif
+
+/* Number of bits in a long long or unsigned long long for the target machine. */
+#if !defined (TARGET_LONG_LONG_BIT)
+#define TARGET_LONG_LONG_BIT (2 * TARGET_LONG_BIT)
+#endif
+
+/* Number of bits in a float for the target machine. */
+#if !defined (TARGET_FLOAT_BIT)
+#define TARGET_FLOAT_BIT (4 * TARGET_CHAR_BIT)
+#endif
+
+/* Number of bits in a double for the target machine. */
+#if !defined (TARGET_DOUBLE_BIT)
+#define TARGET_DOUBLE_BIT (8 * TARGET_CHAR_BIT)
+#endif
+
+/* Number of bits in a long double for the target machine. */
+#if !defined (TARGET_LONG_DOUBLE_BIT)
+#define TARGET_LONG_DOUBLE_BIT (2 * TARGET_DOUBLE_BIT)
+#endif
+
+/* Number of bits in a "complex" for the target machine. */
+#if !defined (TARGET_COMPLEX_BIT)
+#define TARGET_COMPLEX_BIT (2 * TARGET_FLOAT_BIT)
+#endif
+
+/* Number of bits in a "double complex" for the target machine. */
+#if !defined (TARGET_DOUBLE_COMPLEX_BIT)
+#define TARGET_DOUBLE_COMPLEX_BIT (2 * TARGET_DOUBLE_BIT)
+#endif
+
+/* Number of bits in a pointer for the target machine */
+#if !defined (TARGET_PTR_BIT)
+#define TARGET_PTR_BIT TARGET_INT_BIT
+#endif
+
+/* Default to support for "long long" if the host compiler being used is gcc.
+ Config files must define CC_HAS_LONG_LONG to use other host compilers
+ that are capable of supporting "long long", and to cause gdb to use that
+ support. Not defining CC_HAS_LONG_LONG will suppress use of "long long"
+ regardless of what compiler is used.
+
+ FIXME: For now, automatic selection of "long long" as the default when
+ gcc is used is disabled, pending further testing. Concerns include the
+ impact on gdb performance and the universality of bugfree long long
+ support on platforms that do have gcc. Compiling with FORCE_LONG_LONG
+ will select "long long" use for testing purposes. -fnf */
+
+#ifndef CC_HAS_LONG_LONG
+# if defined (__GNUC__) && defined (FORCE_LONG_LONG) /* See FIXME above */
+# define CC_HAS_LONG_LONG 1
+# endif
+#endif
+
+/* LONGEST should not be a typedef, because "unsigned LONGEST" needs to work.
+ CC_HAS_LONG_LONG is defined if the host compiler supports "long long"
+ variables and we wish to make use of that support. */
+
+#ifndef LONGEST
+# ifdef CC_HAS_LONG_LONG
+# define LONGEST long long
+# else
+# define LONGEST long
+# endif
+#endif
+
+/* Convert a LONGEST to an int. This is used in contexts (e.g. number of
+ arguments to a function, number in a value history, register number, etc.)
+ where the value must not be larger than can fit in an int. */
+
+#ifndef longest_to_int
+# ifdef CC_HAS_LONG_LONG
+# define longest_to_int(x) (((x) > INT_MAX || (x) < INT_MIN) \
+ ? (error ("Value out of range."),0) : (int) (x))
+# else
+ /* Assume sizeof (int) == sizeof (long). */
+# define longest_to_int(x) ((int) (x))
+# endif
+#endif
+
+/* If we picked up a copy of CHAR_BIT from a configuration file
+ (which may get it by including <limits.h>) then use it to set
+ the number of bits in a host char. If not, use the same size
+ as the target. */
+
+#if defined (CHAR_BIT)
+#define HOST_CHAR_BIT CHAR_BIT
+#else
+#define HOST_CHAR_BIT TARGET_CHAR_BIT
+#endif
+
+/* Assorted functions we can declare, now that const and volatile are
+ defined. */
+
+extern char *
+savestring PARAMS ((const char *, int));
+
+extern char *
+msavestring PARAMS ((void *, const char *, int));
+
+extern char *
+strsave PARAMS ((const char *));
+
+extern char *
+mstrsave PARAMS ((void *, const char *));
+
+extern char *
+concat PARAMS ((char *, ...));
+
+extern PTR
+xmalloc PARAMS ((long));
+
+extern PTR
+xrealloc PARAMS ((PTR, long));
+
+extern PTR
+xmmalloc PARAMS ((PTR, long));
+
+extern PTR
+xmrealloc PARAMS ((PTR, PTR, long));
+
+extern PTR
+mmalloc PARAMS ((PTR, long));
+
+extern PTR
+mrealloc PARAMS ((PTR, PTR, long));
+
+extern void
+mfree PARAMS ((PTR, PTR));
+
+extern int
+mmcheck PARAMS ((PTR, void (*) (void)));
+
+extern int
+mmtrace PARAMS ((void));
+
+extern int
+parse_escape PARAMS ((char **));
+
+extern const char * const reg_names[];
+
+extern NORETURN void /* Does not return to the caller. */
+error ();
+
+extern NORETURN void /* Does not return to the caller. */
+fatal ();
+
+extern NORETURN void /* Not specified as volatile in ... */
+exit PARAMS ((int)); /* 4.10.4.3 */
+
+extern NORETURN void /* Does not return to the caller. */
+nomem PARAMS ((long));
+
+/* Reasons for calling return_to_top_level. */
+enum return_reason {
+ /* User interrupt. */
+ RETURN_QUIT,
+
+ /* Any other error. */
+ RETURN_ERROR
+};
+
+#define RETURN_MASK_QUIT (1 << (int)RETURN_QUIT)
+#define RETURN_MASK_ERROR (1 << (int)RETURN_ERROR)
+#define RETURN_MASK_ALL (RETURN_MASK_QUIT | RETURN_MASK_ERROR)
+typedef int return_mask;
+
+extern NORETURN void /* Does not return to the caller. */
+return_to_top_level PARAMS ((enum return_reason));
+
+extern int catch_errors PARAMS ((int (*) (char *), void *, char *,
+ return_mask));
+
+extern void
+warning_setup PARAMS ((void));
+
+extern void
+warning ();
+
+/* Global functions from other, non-gdb GNU thingies (libiberty for
+ instance) */
+
+extern char *
+basename PARAMS ((char *));
+
+extern char *
+getenv PARAMS ((const char *));
+
+extern char **
+buildargv PARAMS ((char *));
+
+extern void
+freeargv PARAMS ((char **));
+
+extern char *
+strerrno PARAMS ((int));
+
+extern char *
+strsigno PARAMS ((int));
+
+extern int
+errno_max PARAMS ((void));
+
+extern int
+signo_max PARAMS ((void));
+
+extern int
+strtoerrno PARAMS ((char *));
+
+extern int
+strtosigno PARAMS ((char *));
+
+extern char *
+strsignal PARAMS ((int));
+
+/* From other system libraries */
+
+#ifndef PSIGNAL_IN_SIGNAL_H
+extern void
+psignal PARAMS ((unsigned, const char *));
+#endif
+
+/* For now, we can't include <stdlib.h> because it conflicts with
+ "../include/getopt.h". (FIXME)
+
+ However, if a function is defined in the ANSI C standard and a prototype
+ for that function is defined and visible in any header file in an ANSI
+ conforming environment, then that prototype must match the definition in
+ the ANSI standard. So we can just duplicate them here without conflict,
+ since they must be the same in all conforming ANSI environments. If
+ these cause problems, then the environment is not ANSI conformant. */
+
+#ifdef __STDC__
+#include <stddef.h>
+#endif
+
+extern int
+fclose PARAMS ((FILE *stream)); /* 4.9.5.1 */
+
+extern void
+perror PARAMS ((const char *)); /* 4.9.10.4 */
+
+extern double
+atof PARAMS ((const char *nptr)); /* 4.10.1.1 */
+
+extern int
+atoi PARAMS ((const char *)); /* 4.10.1.2 */
+
+#ifndef MALLOC_INCOMPATIBLE
+
+extern PTR
+malloc PARAMS ((size_t size)); /* 4.10.3.3 */
+
+extern PTR
+realloc PARAMS ((void *ptr, size_t size)); /* 4.10.3.4 */
+
+extern void
+free PARAMS ((void *)); /* 4.10.3.2 */
+
+#endif /* MALLOC_INCOMPATIBLE */
+
+extern void
+qsort PARAMS ((void *base, size_t nmemb, /* 4.10.5.2 */
+ size_t size,
+ int (*comp)(const void *, const void *)));
+
+#ifndef MEM_FNS_DECLARED /* Some non-ANSI use void *, not char *. */
+extern PTR
+memcpy PARAMS ((void *, const void *, size_t)); /* 4.11.2.1 */
+
+extern int
+memcmp PARAMS ((const void *, const void *, size_t)); /* 4.11.4.1 */
+#endif
+
+extern char *
+strchr PARAMS ((const char *, int)); /* 4.11.5.2 */
+
+extern char *
+strrchr PARAMS ((const char *, int)); /* 4.11.5.5 */
+
+extern char *
+strstr PARAMS ((const char *, const char *)); /* 4.11.5.7 */
+
+extern char *
+strtok PARAMS ((char *, const char *)); /* 4.11.5.8 */
+
+#ifndef MEM_FNS_DECLARED /* Some non-ANSI use void *, not char *. */
+extern PTR
+memset PARAMS ((void *, int, size_t)); /* 4.11.6.1 */
+#endif
+
+extern char *
+strerror PARAMS ((int)); /* 4.11.6.2 */
+
+/* Various possibilities for alloca. */
+#ifndef alloca
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# else
+# ifdef sparc
+# include <alloca.h> /* NOTE: Doesn't declare alloca() */
+# endif
+# ifdef __STDC__
+ extern void *alloca (size_t);
+# else /* __STDC__ */
+ extern char *alloca ();
+# endif
+# endif
+#endif
+
+/* TARGET_BYTE_ORDER and HOST_BYTE_ORDER must be defined to one of these. */
+
+#if !defined (BIG_ENDIAN)
+#define BIG_ENDIAN 4321
+#endif
+
+#if !defined (LITTLE_ENDIAN)
+#define LITTLE_ENDIAN 1234
+#endif
+
+/* Target-system-dependent parameters for GDB. */
+
+/* Target machine definition. This will be a symlink to one of the
+ tm-*.h files, built by the `configure' script. */
+
+#include "tm.h"
+
+/* 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 !defined (BITS_BIG_ENDIAN)
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BITS_BIG_ENDIAN 1
+#endif /* Big endian. */
+
+#if TARGET_BYTE_ORDER == LITTLE_ENDIAN
+#define BITS_BIG_ENDIAN 0
+#endif /* Little endian. */
+#endif /* BITS_BIG_ENDIAN not defined. */
+
+/* Swap LEN bytes at BUFFER between target and host byte-order. This is
+ the wrong way to do byte-swapping because it assumes that you have a way
+ to have a host variable of exactly the right size.
+ extract_* are the right way. */
+#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. */
+
+/* In findvar.c. */
+LONGEST extract_signed_integer PARAMS ((void *, int));
+unsigned LONGEST extract_unsigned_integer PARAMS ((void *, int));
+CORE_ADDR extract_address PARAMS ((void *, int));
+
+void store_signed_integer PARAMS ((void *, int, LONGEST));
+void store_unsigned_integer PARAMS ((void *, int, unsigned LONGEST));
+void store_address PARAMS ((void *, int, CORE_ADDR));
+
+/* 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. This is used only for addresses of instructions, and even then
+ I'm not sure it's used in all contexts. It exists to deal with there
+ being a few stray bits in the PC which would mislead us, not as some sort
+ of generic thing to handle alignment or segmentation (it's possible it
+ should be in TARGET_READ_PC instead). */
+#if !defined (ADDR_BITS_REMOVE)
+#define ADDR_BITS_REMOVE(addr) (addr)
+#endif /* No ADDR_BITS_REMOVE. */
+
+/* From valops.c */
+
+extern CORE_ADDR
+push_bytes PARAMS ((CORE_ADDR, char *, int));
+
+/* In some modules, we don't have a definition of REGISTER_TYPE yet, so we
+ must avoid prototyping this function for now. FIXME. Should be:
+extern CORE_ADDR
+push_word PARAMS ((CORE_ADDR, REGISTER_TYPE));
+ */
+extern CORE_ADDR
+push_word ();
+
+/* Some parts of gdb might be considered optional, in the sense that they
+ are not essential for being able to build a working, usable debugger
+ for a specific environment. For example, the maintenance commands
+ are there for the benefit of gdb maintainers. As another example,
+ some environments really don't need gdb's that are able to read N
+ different object file formats. In order to make it possible (but
+ not necessarily recommended) to build "stripped down" versions of
+ gdb, the following defines control selective compilation of those
+ parts of gdb which can be safely left out when necessary. Note that
+ the default is to include everything. */
+
+#ifndef MAINTENANCE_CMDS
+#define MAINTENANCE_CMDS 1
+#endif
+
+#endif /* !defined (DEFS_H) */
diff --git a/gnu/usr.bin/gdb/gdb/demangle.c b/gnu/usr.bin/gdb/gdb/demangle.c
new file mode 100644
index 000000000000..a134bb70ad98
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/demangle.c
@@ -0,0 +1,190 @@
+/* Basic C++ demangling support for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This file contains support code for C++ demangling that is common
+ to a styles of demangling, and GDB specific. */
+
+#include "defs.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "demangle.h"
+#include <string.h>
+
+/* Select the default C++ demangling style to use. The default is "auto",
+ which allows gdb to attempt to pick an appropriate demangling style for
+ the executable it has loaded. It can be set to a specific style ("gnu",
+ "lucid", "arm", etc.) in which case gdb will never attempt to do auto
+ selection of the style unless you do an explicit "set demangle auto".
+ To select one of these as the default, set DEFAULT_DEMANGLING_STYLE in
+ the appropriate target configuration file. */
+
+#ifndef DEFAULT_DEMANGLING_STYLE
+# define DEFAULT_DEMANGLING_STYLE AUTO_DEMANGLING_STYLE_STRING
+#endif
+
+/* String name for the current demangling style. Set by the "set demangling"
+ command, printed as part of the output by the "show demangling" command. */
+
+static char *current_demangling_style_string;
+
+/* List of supported demangling styles. Contains the name of the style as
+ seen by the user, and the enum value that corresponds to that style. */
+
+static const struct demangler
+{
+ char *demangling_style_name;
+ enum demangling_styles demangling_style;
+ char *demangling_style_doc;
+} demanglers [] =
+{
+ {AUTO_DEMANGLING_STYLE_STRING,
+ auto_demangling,
+ "Automatic selection based on executable"},
+ {GNU_DEMANGLING_STYLE_STRING,
+ gnu_demangling,
+ "GNU (g++) style demangling"},
+ {LUCID_DEMANGLING_STYLE_STRING,
+ lucid_demangling,
+ "Lucid (lcc) style demangling"},
+ {ARM_DEMANGLING_STYLE_STRING,
+ arm_demangling,
+ "ARM style demangling"},
+ {NULL, unknown_demangling, NULL}
+};
+
+/* show current demangling style. */
+
+static void
+show_demangling_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ /* done automatically by show command. */
+}
+
+
+/* set current demangling style. called by the "set demangling" command
+ after it has updated the current_demangling_style_string to match
+ what the user has entered.
+
+ if the user has entered a string that matches a known demangling style
+ name in the demanglers[] array then just leave the string alone and update
+ the current_demangling_style enum value to match.
+
+ if the user has entered a string that doesn't match, including an empty
+ string, then print a list of the currently known styles and restore
+ the current_demangling_style_string to match the current_demangling_style
+ enum value.
+
+ Note: Assumes that current_demangling_style_string always points to
+ a malloc'd string, even if it is a null-string. */
+
+static void
+set_demangling_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ const struct demangler *dem;
+
+ /* First just try to match whatever style name the user supplied with
+ one of the known ones. Don't bother special casing for an empty
+ name, we just treat it as any other style name that doesn't match.
+ If we match, update the current demangling style enum. */
+
+ for (dem = demanglers; dem -> demangling_style_name != NULL; dem++)
+ {
+ if (STREQ (current_demangling_style_string,
+ dem -> demangling_style_name))
+ {
+ current_demangling_style = dem -> demangling_style;
+ break;
+ }
+ }
+
+ /* Check to see if we found a match. If not, gripe about any non-empty
+ style name and supply a list of valid ones. FIXME: This should
+ probably be done with some sort of completion and with help. */
+
+ if (dem -> demangling_style_name == NULL)
+ {
+ if (*current_demangling_style_string != '\0')
+ {
+ printf ("Unknown demangling style `%s'.\n",
+ current_demangling_style_string);
+ }
+ printf ("The currently understood settings are:\n\n");
+ for (dem = demanglers; dem -> demangling_style_name != NULL; dem++)
+ {
+ printf ("%-10s %s\n", dem -> demangling_style_name,
+ dem -> demangling_style_doc);
+ if (dem -> demangling_style == current_demangling_style)
+ {
+ free (current_demangling_style_string);
+ current_demangling_style_string =
+ strdup (dem -> demangling_style_name);
+ }
+ }
+ if (current_demangling_style == unknown_demangling)
+ {
+ /* This can happen during initialization if gdb is compiled with
+ a DEMANGLING_STYLE value that is unknown, so pick the first
+ one as the default. */
+ current_demangling_style = demanglers[0].demangling_style;
+ current_demangling_style_string =
+ strdup (demanglers[0].demangling_style_name);
+ warning ("`%s' style demangling chosen as the default.\n",
+ current_demangling_style_string);
+ }
+ }
+}
+
+/* Fake a "set demangling" command. */
+
+void
+set_demangling_style (style)
+ char *style;
+{
+ if (current_demangling_style_string != NULL)
+ {
+ free (current_demangling_style_string);
+ }
+ current_demangling_style_string = strdup (style);
+ set_demangling_command ((char *) NULL, 0);
+}
+
+void
+_initialize_demangler ()
+{
+ struct cmd_list_element *set, *show;
+
+ set = add_set_cmd ("demangle-style", class_support, var_string_noescape,
+ (char *) &current_demangling_style_string,
+ "Set the current C++ demangling style.\n\
+Use `set demangle-style' without arguments for a list of demangling styles.",
+ &setlist);
+ show = add_show_from_set (set, &showlist);
+ set -> function.cfunc = set_demangling_command;
+ show -> function.cfunc = show_demangling_command;
+
+ /* Set the default demangling style chosen at compilation time. */
+ set_demangling_style (DEFAULT_DEMANGLING_STYLE);
+ set_cplus_marker_for_demangling (CPLUS_MARKER);
+}
diff --git a/gnu/usr.bin/gdb/gdb/demangle.h b/gnu/usr.bin/gdb/gdb/demangle.h
new file mode 100644
index 000000000000..4f191a2e1ade
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/demangle.h
@@ -0,0 +1,77 @@
+/* Defs for interface to demanglers.
+ Copyright 1992 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#if !defined (DEMANGLE_H)
+#define DEMANGLE_H
+
+#include <ansidecl.h>
+
+/* Options passed to cplus_demangle (in 2nd parameter). */
+
+#define DMGL_NO_OPTS 0 /* For readability... */
+#define DMGL_PARAMS (1 << 0) /* Include function args */
+#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
+
+#define DMGL_AUTO (1 << 8)
+#define DMGL_GNU (1 << 9)
+#define DMGL_LUCID (1 << 10)
+#define DMGL_ARM (1 << 11)
+/* If none of these are set, use 'current_demangling_style' as the default. */
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM)
+
+/* Enumeration of possible demangling styles.
+
+ Lucid and ARM styles are still kept logically distinct, even though
+ they now both behave identically. The resulting style is actual the
+ union of both. I.E. either style recognizes both "__pt__" and "__rf__"
+ for operator "->", even though the first is lucid style and the second
+ is ARM style. (FIXME?) */
+
+extern enum demangling_styles
+{
+ unknown_demangling = 0,
+ auto_demangling = DMGL_AUTO,
+ gnu_demangling = DMGL_GNU,
+ lucid_demangling = DMGL_LUCID,
+ arm_demangling = DMGL_ARM
+} current_demangling_style;
+
+/* Define string names for the various demangling styles. */
+
+#define AUTO_DEMANGLING_STYLE_STRING "auto"
+#define GNU_DEMANGLING_STYLE_STRING "gnu"
+#define LUCID_DEMANGLING_STYLE_STRING "lucid"
+#define ARM_DEMANGLING_STYLE_STRING "arm"
+
+/* Some macros to test what demangling style is active. */
+
+#define CURRENT_DEMANGLING_STYLE current_demangling_style
+#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO)
+#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU)
+#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID)
+#define ARM_DEMANGLING (CURRENT_DEMANGLING_STYLE & DMGL_ARM)
+
+extern char *
+cplus_demangle PARAMS ((CONST char *mangled, int options));
+
+/* Note: This sets global state. FIXME if you care about multi-threading. */
+
+extern void
+set_cplus_marker_for_demangling PARAMS ((int ch));
+
+#endif /* DEMANGLE_H */
diff --git a/gnu/usr.bin/gdb/gdb/dis-asm.h b/gnu/usr.bin/gdb/gdb/dis-asm.h
new file mode 100644
index 000000000000..e7f106c318cb
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/dis-asm.h
@@ -0,0 +1,176 @@
+/* Interface between the opcode library and its callers.
+ Written by Cygnus Support, 1993.
+
+ The opcode library (libopcodes.a) provides instruction decoders for
+ a large variety of instruction sets, callable with an identical
+ interface, for making instruction-processing programs more independent
+ of the instruction set being processed. */
+
+#include <stdio.h>
+#include "bfd.h"
+
+typedef int (*fprintf_ftype) PARAMS((FILE*, const char*, ...));
+
+enum dis_insn_type {
+ dis_noninsn, /* Not a valid instruction */
+ dis_nonbranch, /* Not a branch instruction */
+ dis_branch, /* Unconditional branch */
+ dis_condbranch, /* Conditional branch */
+ dis_jsr, /* Jump to subroutine */
+ dis_condjsr, /* Conditional jump to subroutine */
+ dis_dref, /* Data reference instruction */
+ dis_dref2, /* Two data references in instruction */
+};
+
+/* This struct is passed into the instruction decoding routine,
+ and is passed back out into each callback. The various fields are used
+ for conveying information from your main routine into your callbacks,
+ for passing information into the instruction decoders (such as the
+ addresses of the callback functions), or for passing information
+ back from the instruction decoders to their callers.
+
+ It must be initialized before it is first passed; this can be done
+ by hand, or using one of the initialization macros below. */
+
+typedef struct disassemble_info {
+ fprintf_ftype fprintf_func;
+ FILE *stream;
+ PTR application_data;
+
+ /* For use by the disassembler. */
+ int flags;
+ PTR private_data;
+
+ /* Function used to get bytes to disassemble. MEMADDR is the
+ address of the stuff to be disassembled, MYADDR is the address to
+ put the bytes in, and LENGTH is the number of bytes to read.
+ INFO is a pointer to this struct.
+ Returns an errno value or 0 for success. */
+ int (*read_memory_func)
+ PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, int length,
+ struct disassemble_info *info));
+
+ /* Function which should be called if we get an error that we can't
+ recover from. STATUS is the errno value from read_memory_func and
+ MEMADDR is the address that we were trying to read. INFO is a
+ pointer to this struct. */
+ void (*memory_error_func)
+ PARAMS ((int status, bfd_vma memaddr, struct disassemble_info *info));
+
+ /* Function called to print ADDR. */
+ void (*print_address_func)
+ PARAMS ((bfd_vma addr, struct disassemble_info *info));
+
+ /* These are for buffer_read_memory. */
+ bfd_byte *buffer;
+ bfd_vma buffer_vma;
+ int buffer_length;
+
+ /* Results from instruction decoders. Not all decoders yet support
+ this information. This info is set each time an instruction is
+ decoded, and is only valid for the last such instruction.
+
+ To determine whether this decoder supports this information, set
+ insn_info_valid to 0, decode an instruction, then check it. */
+
+ char insn_info_valid; /* Branch info has been set. */
+ char branch_delay_insns; /* How many sequential insn's will run before
+ a branch takes effect. (0 = normal) */
+ char data_size; /* Size of data reference in insn, in bytes */
+ enum dis_insn_type insn_type; /* Type of instruction */
+ bfd_vma target; /* Target address of branch or dref, if known;
+ zero if unknown. */
+ bfd_vma target2; /* Second target address for dref2 */
+
+} disassemble_info;
+
+
+
+
+
+
+/* Standard disassemblers. Disassemble one instruction at the given
+ target address. Return number of bytes processed. */
+typedef int (*disassembler_ftype)
+ PARAMS((bfd_vma, disassemble_info *));
+
+extern int print_insn_big_mips PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_mips PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i386 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m68k PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_z8001 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_z8002 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8300 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8300h PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8500 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_sparc PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_big_a29k PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_a29k PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i960 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_sh PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_hppa PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m88k PARAMS ((bfd_vma, disassemble_info*));
+
+
+
+
+
+
+/* This block of definitions is for particular callers who read instructions
+ into a buffer before calling the instruction decoder. */
+
+/* Here is a function which callers may wish to use for read_memory_func.
+ It gets bytes from a buffer. */
+extern int buffer_read_memory
+ PARAMS ((bfd_vma, bfd_byte *, int, struct disassemble_info *));
+
+/* This function goes with buffer_read_memory.
+ It prints a message using info->fprintf_func and info->stream. */
+extern void perror_memory PARAMS ((int, bfd_vma, struct disassemble_info *));
+
+
+/* Just print the address is hex. This is included for completeness even
+ though both GDB and objdump provide their own (to print symbolic
+ addresses). */
+extern void generic_print_address
+ PARAMS ((bfd_vma, struct disassemble_info *));
+
+#define INIT_DISASSEMBLE_INFO(INFO, STREAM) \
+ (INFO).fprintf_func = (fprintf_ftype)fprintf, \
+ (INFO).stream = (STREAM), \
+ (INFO).buffer = NULL, \
+ (INFO).buffer_vma = 0, \
+ (INFO).buffer_length = 0, \
+ (INFO).read_memory_func = buffer_read_memory, \
+ (INFO).memory_error_func = perror_memory, \
+ (INFO).print_address_func = generic_print_address, \
+ (INFO).insn_info_valid = 0
+
+
+
+
+/* This block of definitions is for calling the instruction decoders
+ from GDB. */
+
+/* GDB--Like target_read_memory, but slightly different parameters. */
+extern int
+dis_asm_read_memory PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, int len,
+ disassemble_info *info));
+
+/* GDB--Like memory_error with slightly different parameters. */
+extern void
+dis_asm_memory_error
+ PARAMS ((int status, bfd_vma memaddr, disassemble_info *info));
+
+/* GDB--Like print_address with slightly different parameters. */
+extern void
+dis_asm_print_address PARAMS ((bfd_vma addr, disassemble_info *info));
+
+#define GDB_INIT_DISASSEMBLE_INFO(INFO, STREAM) \
+ (INFO).fprintf_func = (fprintf_ftype)fprintf_filtered, \
+ (INFO).stream = (STREAM), \
+ (INFO).read_memory_func = dis_asm_read_memory, \
+ (INFO).memory_error_func = dis_asm_memory_error, \
+ (INFO).print_address_func = dis_asm_print_address, \
+ (INFO).insn_info_valid = 0
diff --git a/gnu/usr.bin/gdb/gdb/dis-buf.c b/gnu/usr.bin/gdb/gdb/dis-buf.c
new file mode 100644
index 000000000000..d07da6fcff31
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/dis-buf.c
@@ -0,0 +1,69 @@
+/* Disassemble from a buffer, for GNU.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "dis-asm.h"
+#include <errno.h>
+
+/* Get LENGTH bytes from info's buffer, at target address memaddr.
+ Transfer them to myaddr. */
+int
+buffer_read_memory (memaddr, myaddr, length, info)
+ bfd_vma memaddr;
+ bfd_byte *myaddr;
+ int length;
+ struct disassemble_info *info;
+{
+ if (memaddr < info->buffer_vma
+ || memaddr + length > info->buffer_vma + info->buffer_length)
+ /* Out of bounds. Use EIO because GDB uses it. */
+ return EIO;
+ memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
+ return 0;
+}
+
+/* Print an error message. We can assume that this is in response to
+ an error return from buffer_read_memory. */
+void
+perror_memory (status, memaddr, info)
+ int status;
+ bfd_vma memaddr;
+ struct disassemble_info *info;
+{
+ if (status != EIO)
+ /* Can't happen. */
+ (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
+ else
+ /* Actually, address between memaddr and memaddr + len was
+ out of bounds. */
+ (*info->fprintf_func) (info->stream,
+ "Address 0x%x is out of bounds.\n", memaddr);
+}
+
+/* This could be in a separate file, to save miniscule amounts of space
+ in statically linked executables. */
+
+/* Just print the address is hex. This is included for completeness even
+ though both GDB and objdump provide their own (to print symbolic
+ addresses). */
+
+void
+generic_print_address (addr, info)
+ bfd_vma addr;
+ struct disassemble_info *info;
+{
+ (*info->fprintf_func) (info->stream, "0x%x", addr);
+}
diff --git a/gnu/usr.bin/gdb/gdb/dwarfread.c b/gnu/usr.bin/gdb/gdb/dwarfread.c
new file mode 100644
index 000000000000..5d19bf8d0b07
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/dwarfread.c
@@ -0,0 +1,3866 @@
+/* DWARF debugging format support for GDB.
+ Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support. Portions based on dbxread.c,
+ mipsread.c, coffread.c, and dwarfread.c from a Data General SVR4 gdb port.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+
+FIXME: Do we need to generate dependencies in partial symtabs?
+(Perhaps we don't need to).
+
+FIXME: Resolve minor differences between what information we put in the
+partial symbol table and what dbxread puts in. For example, we don't yet
+put enum constants there. And dbxread seems to invent a lot of typedefs
+we never see. Use the new printpsym command to see the partial symbol table
+contents.
+
+FIXME: Figure out a better way to tell gdb about the name of the function
+contain the user's entry point (I.E. main())
+
+FIXME: See other FIXME's and "ifdef 0" scattered throughout the code for
+other things to work on, if you get bored. :-)
+
+*/
+
+#include "defs.h"
+#include "bfd.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include <time.h> /* For time_t in libbfd.h. */
+#include <sys/types.h> /* For time_t, if not in time.h. */
+#include "libbfd.h" /* FIXME Secret Internal BFD stuff (bfd_read) */
+#include "elf/dwarf.h"
+#include "buildsym.h"
+#include "demangle.h"
+#include "expression.h" /* Needed for enum exp_opcode in language.h, sigh... */
+#include "language.h"
+#include "complaints.h"
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+
+/* FIXME -- convert this to SEEK_SET a la POSIX, move to config files. */
+#ifndef L_SET
+#define L_SET 0
+#endif
+
+/* Some macros to provide DIE info for complaints. */
+
+#define DIE_ID (curdie!=NULL ? curdie->die_ref : 0)
+#define DIE_NAME (curdie!=NULL && curdie->at_name!=NULL) ? curdie->at_name : ""
+
+/* Complaints that can be issued during DWARF debug info reading. */
+
+struct complaint no_bfd_get_N =
+{
+ "DIE @ 0x%x \"%s\", no bfd support for %d byte data object", 0, 0
+};
+
+struct complaint malformed_die =
+{
+ "DIE @ 0x%x \"%s\", malformed DIE, bad length (%d bytes)", 0, 0
+};
+
+struct complaint bad_die_ref =
+{
+ "DIE @ 0x%x \"%s\", reference to DIE (0x%x) outside compilation unit", 0, 0
+};
+
+struct complaint unknown_attribute_form =
+{
+ "DIE @ 0x%x \"%s\", unknown attribute form (0x%x)", 0, 0
+};
+
+struct complaint unknown_attribute_length =
+{
+ "DIE @ 0x%x \"%s\", unknown attribute length, skipped remaining attributes", 0, 0
+};
+
+struct complaint unexpected_fund_type =
+{
+ "DIE @ 0x%x \"%s\", unexpected fundamental type 0x%x", 0, 0
+};
+
+struct complaint unknown_type_modifier =
+{
+ "DIE @ 0x%x \"%s\", unknown type modifier %u", 0, 0
+};
+
+struct complaint volatile_ignored =
+{
+ "DIE @ 0x%x \"%s\", type modifier 'volatile' ignored", 0, 0
+};
+
+struct complaint const_ignored =
+{
+ "DIE @ 0x%x \"%s\", type modifier 'const' ignored", 0, 0
+};
+
+struct complaint botched_modified_type =
+{
+ "DIE @ 0x%x \"%s\", botched modified type decoding (mtype 0x%x)", 0, 0
+};
+
+struct complaint op_deref2 =
+{
+ "DIE @ 0x%x \"%s\", OP_DEREF2 address 0x%x not handled", 0, 0
+};
+
+struct complaint op_deref4 =
+{
+ "DIE @ 0x%x \"%s\", OP_DEREF4 address 0x%x not handled", 0, 0
+};
+
+struct complaint basereg_not_handled =
+{
+ "DIE @ 0x%x \"%s\", BASEREG %d not handled", 0, 0
+};
+
+struct complaint dup_user_type_allocation =
+{
+ "DIE @ 0x%x \"%s\", internal error: duplicate user type allocation", 0, 0
+};
+
+struct complaint dup_user_type_definition =
+{
+ "DIE @ 0x%x \"%s\", internal error: duplicate user type definition", 0, 0
+};
+
+struct complaint missing_tag =
+{
+ "DIE @ 0x%x \"%s\", missing class, structure, or union tag", 0, 0
+};
+
+struct complaint bad_array_element_type =
+{
+ "DIE @ 0x%x \"%s\", bad array element type attribute 0x%x", 0, 0
+};
+
+struct complaint subscript_data_items =
+{
+ "DIE @ 0x%x \"%s\", can't decode subscript data items", 0, 0
+};
+
+struct complaint unhandled_array_subscript_format =
+{
+ "DIE @ 0x%x \"%s\", array subscript format 0x%x not handled yet", 0, 0
+};
+
+struct complaint unknown_array_subscript_format =
+{
+ "DIE @ 0x%x \"%s\", unknown array subscript format %x", 0, 0
+};
+
+struct complaint not_row_major =
+{
+ "DIE @ 0x%x \"%s\", array not row major; not handled correctly", 0, 0
+};
+
+typedef unsigned int DIE_REF; /* Reference to a DIE */
+
+#ifndef GCC_PRODUCER
+#define GCC_PRODUCER "GNU C "
+#endif
+
+#ifndef GPLUS_PRODUCER
+#define GPLUS_PRODUCER "GNU C++ "
+#endif
+
+#ifndef LCC_PRODUCER
+#define LCC_PRODUCER "NCR C/C++"
+#endif
+
+#ifndef CHILL_PRODUCER
+#define CHILL_PRODUCER "GNU Chill "
+#endif
+
+/* Flags to target_to_host() that tell whether or not the data object is
+ expected to be signed. Used, for example, when fetching a signed
+ integer in the target environment which is used as a signed integer
+ in the host environment, and the two environments have different sized
+ ints. In this case, *somebody* has to sign extend the smaller sized
+ int. */
+
+#define GET_UNSIGNED 0 /* No sign extension required */
+#define GET_SIGNED 1 /* Sign extension required */
+
+/* Defines for things which are specified in the document "DWARF Debugging
+ Information Format" published by UNIX International, Programming Languages
+ SIG. These defines are based on revision 1.0.0, Jan 20, 1992. */
+
+#define SIZEOF_DIE_LENGTH 4
+#define SIZEOF_DIE_TAG 2
+#define SIZEOF_ATTRIBUTE 2
+#define SIZEOF_FORMAT_SPECIFIER 1
+#define SIZEOF_FMT_FT 2
+#define SIZEOF_LINETBL_LENGTH 4
+#define SIZEOF_LINETBL_LINENO 4
+#define SIZEOF_LINETBL_STMT 2
+#define SIZEOF_LINETBL_DELTA 4
+#define SIZEOF_LOC_ATOM_CODE 1
+
+#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified */
+
+/* Macros that return the sizes of various types of data in the target
+ environment.
+
+ FIXME: Currently these are just compile time constants (as they are in
+ other parts of gdb as well). They need to be able to get the right size
+ either from the bfd or possibly from the DWARF info. It would be nice if
+ the DWARF producer inserted DIES that describe the fundamental types in
+ the target environment into the DWARF info, similar to the way dbx stabs
+ producers produce information about their fundamental types. */
+
+#define TARGET_FT_POINTER_SIZE(objfile) (TARGET_PTR_BIT / TARGET_CHAR_BIT)
+#define TARGET_FT_LONG_SIZE(objfile) (TARGET_LONG_BIT / TARGET_CHAR_BIT)
+
+/* The Amiga SVR4 header file <dwarf.h> defines AT_element_list as a
+ FORM_BLOCK2, and this is the value emitted by the AT&T compiler.
+ However, the Issue 2 DWARF specification from AT&T defines it as
+ a FORM_BLOCK4, as does the latest specification from UI/PLSIG.
+ For backwards compatibility with the AT&T compiler produced executables
+ we define AT_short_element_list for this variant. */
+
+#define AT_short_element_list (0x00f0|FORM_BLOCK2)
+
+/* External variables referenced. */
+
+extern int info_verbose; /* From main.c; nonzero => verbose */
+extern char *warning_pre_print; /* From utils.c */
+
+/* The DWARF debugging information consists of two major pieces,
+ one is a block of DWARF Information Entries (DIE's) and the other
+ is a line number table. The "struct dieinfo" structure contains
+ the information for a single DIE, the one currently being processed.
+
+ In order to make it easier to randomly access the attribute fields
+ of the current DIE, which are specifically unordered within the DIE,
+ each DIE is scanned and an instance of the "struct dieinfo"
+ structure is initialized.
+
+ Initialization is done in two levels. The first, done by basicdieinfo(),
+ just initializes those fields that are vital to deciding whether or not
+ to use this DIE, how to skip past it, etc. The second, done by the
+ function completedieinfo(), fills in the rest of the information.
+
+ Attributes which have block forms are not interpreted at the time
+ the DIE is scanned, instead we just save pointers to the start
+ of their value fields.
+
+ Some fields have a flag <name>_p that is set when the value of the
+ field is valid (I.E. we found a matching attribute in the DIE). Since
+ we may want to test for the presence of some attributes in the DIE,
+ such as AT_low_pc, without restricting the values of the field,
+ we need someway to note that we found such an attribute.
+
+ */
+
+typedef char BLOCK;
+
+struct dieinfo {
+ char * die; /* Pointer to the raw DIE data */
+ unsigned long die_length; /* Length of the raw DIE data */
+ DIE_REF die_ref; /* Offset of this DIE */
+ unsigned short die_tag; /* Tag for this DIE */
+ unsigned long at_padding;
+ unsigned long at_sibling;
+ BLOCK * at_location;
+ char * at_name;
+ unsigned short at_fund_type;
+ BLOCK * at_mod_fund_type;
+ unsigned long at_user_def_type;
+ BLOCK * at_mod_u_d_type;
+ unsigned short at_ordering;
+ BLOCK * at_subscr_data;
+ unsigned long at_byte_size;
+ unsigned short at_bit_offset;
+ unsigned long at_bit_size;
+ BLOCK * at_element_list;
+ unsigned long at_stmt_list;
+ unsigned long at_low_pc;
+ unsigned long at_high_pc;
+ unsigned long at_language;
+ unsigned long at_member;
+ unsigned long at_discr;
+ BLOCK * at_discr_value;
+ BLOCK * at_string_length;
+ char * at_comp_dir;
+ char * at_producer;
+ unsigned long at_start_scope;
+ unsigned long at_stride_size;
+ unsigned long at_src_info;
+ char * at_prototyped;
+ unsigned int has_at_low_pc:1;
+ unsigned int has_at_stmt_list:1;
+ unsigned int has_at_byte_size:1;
+ unsigned int short_element_list:1;
+};
+
+static int diecount; /* Approximate count of dies for compilation unit */
+static struct dieinfo *curdie; /* For warnings and such */
+
+static char *dbbase; /* Base pointer to dwarf info */
+static int dbsize; /* Size of dwarf info in bytes */
+static int dbroff; /* Relative offset from start of .debug section */
+static char *lnbase; /* Base pointer to line section */
+static int isreg; /* Kludge to identify register variables */
+/* Kludge to identify basereg references. Nonzero if we have an offset
+ relative to a basereg. */
+static int offreg;
+/* Which base register is it relative to? */
+static int basereg;
+
+/* This value is added to each symbol value. FIXME: Generalize to
+ the section_offsets structure used by dbxread (once this is done,
+ pass the appropriate section number to end_symtab). */
+static CORE_ADDR baseaddr; /* Add to each symbol value */
+
+/* The section offsets used in the current psymtab or symtab. FIXME,
+ only used to pass one value (baseaddr) at the moment. */
+static struct section_offsets *base_section_offsets;
+
+/* Each partial symbol table entry contains a pointer to private data for the
+ read_symtab() function to use when expanding a partial symbol table entry
+ to a full symbol table entry. For DWARF debugging info, this data is
+ contained in the following structure and macros are provided for easy
+ access to the members given a pointer to a partial symbol table entry.
+
+ dbfoff Always the absolute file offset to the start of the ".debug"
+ section for the file containing the DIE's being accessed.
+
+ dbroff Relative offset from the start of the ".debug" access to the
+ first DIE to be accessed. When building the partial symbol
+ table, this value will be zero since we are accessing the
+ entire ".debug" section. When expanding a partial symbol
+ table entry, this value will be the offset to the first
+ DIE for the compilation unit containing the symbol that
+ triggers the expansion.
+
+ dblength The size of the chunk of DIE's being examined, in bytes.
+
+ lnfoff The absolute file offset to the line table fragment. Ignored
+ when building partial symbol tables, but used when expanding
+ them, and contains the absolute file offset to the fragment
+ of the ".line" section containing the line numbers for the
+ current compilation unit.
+ */
+
+struct dwfinfo {
+ file_ptr dbfoff; /* Absolute file offset to start of .debug section */
+ int dbroff; /* Relative offset from start of .debug section */
+ int dblength; /* Size of the chunk of DIE's being examined */
+ file_ptr lnfoff; /* Absolute file offset to line table fragment */
+};
+
+#define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff)
+#define DBROFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbroff)
+#define DBLENGTH(p) (((struct dwfinfo *)((p)->read_symtab_private))->dblength)
+#define LNFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->lnfoff)
+
+/* The generic symbol table building routines have separate lists for
+ file scope symbols and all all other scopes (local scopes). So
+ we need to select the right one to pass to add_symbol_to_list().
+ We do it by keeping a pointer to the correct list in list_in_scope.
+
+ FIXME: The original dwarf code just treated the file scope as the first
+ local scope, and all other local scopes as nested local scopes, and worked
+ fine. Check to see if we really need to distinguish these in buildsym.c */
+
+struct pending **list_in_scope = &file_symbols;
+
+/* DIES which have user defined types or modified user defined types refer to
+ other DIES for the type information. Thus we need to associate the offset
+ of a DIE for a user defined type with a pointer to the type information.
+
+ Originally this was done using a simple but expensive algorithm, with an
+ array of unsorted structures, each containing an offset/type-pointer pair.
+ This array was scanned linearly each time a lookup was done. The result
+ was that gdb was spending over half it's startup time munging through this
+ array of pointers looking for a structure that had the right offset member.
+
+ The second attempt used the same array of structures, but the array was
+ sorted using qsort each time a new offset/type was recorded, and a binary
+ search was used to find the type pointer for a given DIE offset. This was
+ even slower, due to the overhead of sorting the array each time a new
+ offset/type pair was entered.
+
+ The third attempt uses a fixed size array of type pointers, indexed by a
+ value derived from the DIE offset. Since the minimum DIE size is 4 bytes,
+ we can divide any DIE offset by 4 to obtain a unique index into this fixed
+ size array. Since each element is a 4 byte pointer, it takes exactly as
+ much memory to hold this array as to hold the DWARF info for a given
+ compilation unit. But it gets freed as soon as we are done with it.
+ This has worked well in practice, as a reasonable tradeoff between memory
+ consumption and speed, without having to resort to much more complicated
+ algorithms. */
+
+static struct type **utypes; /* Pointer to array of user type pointers */
+static int numutypes; /* Max number of user type pointers */
+
+/* Maintain an array of referenced fundamental types for the current
+ compilation unit being read. For DWARF version 1, we have to construct
+ the fundamental types on the fly, since no information about the
+ fundamental types is supplied. Each such fundamental type is created by
+ calling a language dependent routine to create the type, and then a
+ pointer to that type is then placed in the array at the index specified
+ by it's FT_<TYPENAME> value. The array has a fixed size set by the
+ FT_NUM_MEMBERS compile time constant, which is the number of predefined
+ fundamental types gdb knows how to construct. */
+
+static struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */
+
+/* Record the language for the compilation unit which is currently being
+ processed. We know it once we have seen the TAG_compile_unit DIE,
+ and we need it while processing the DIE's for that compilation unit.
+ It is eventually saved in the symtab structure, but we don't finalize
+ the symtab struct until we have processed all the DIE's for the
+ compilation unit. We also need to get and save a pointer to the
+ language struct for this language, so we can call the language
+ dependent routines for doing things such as creating fundamental
+ types. */
+
+static enum language cu_language;
+static const struct language_defn *cu_language_defn;
+
+/* Forward declarations of static functions so we don't have to worry
+ about ordering within this file. */
+
+static int
+attribute_size PARAMS ((unsigned int));
+
+static unsigned long
+target_to_host PARAMS ((char *, int, int, struct objfile *));
+
+static void
+add_enum_psymbol PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+handle_producer PARAMS ((char *));
+
+static void
+read_file_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+
+static void
+read_func_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+
+static void
+read_lexical_block_scope PARAMS ((struct dieinfo *, char *, char *,
+ struct objfile *));
+
+static void
+scan_partial_symbols PARAMS ((char *, char *, struct objfile *));
+
+static void
+scan_compilation_units PARAMS ((char *, char *, file_ptr,
+ file_ptr, struct objfile *));
+
+static void
+add_partial_symbol PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+init_psymbol_list PARAMS ((struct objfile *, int));
+
+static void
+basicdieinfo PARAMS ((struct dieinfo *, char *, struct objfile *));
+
+static void
+completedieinfo PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+dwarf_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+static void
+psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+
+static void
+read_ofile_symtab PARAMS ((struct partial_symtab *));
+
+static void
+process_dies PARAMS ((char *, char *, struct objfile *));
+
+static void
+read_structure_scope PARAMS ((struct dieinfo *, char *, char *,
+ struct objfile *));
+
+static struct type *
+decode_array_element_type PARAMS ((char *));
+
+static struct type *
+decode_subscript_data_item PARAMS ((char *, char *));
+
+static void
+dwarf_read_array_type PARAMS ((struct dieinfo *));
+
+static void
+read_tag_pointer_type PARAMS ((struct dieinfo *dip));
+
+static void
+read_tag_string_type PARAMS ((struct dieinfo *dip));
+
+static void
+read_subroutine_type PARAMS ((struct dieinfo *, char *, char *));
+
+static void
+read_enumeration PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+
+static struct type *
+struct_type PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+
+static struct type *
+enum_type PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+decode_line_numbers PARAMS ((char *));
+
+static struct type *
+decode_die_type PARAMS ((struct dieinfo *));
+
+static struct type *
+decode_mod_fund_type PARAMS ((char *));
+
+static struct type *
+decode_mod_u_d_type PARAMS ((char *));
+
+static struct type *
+decode_modified_type PARAMS ((char *, unsigned int, int));
+
+static struct type *
+decode_fund_type PARAMS ((unsigned int));
+
+static char *
+create_name PARAMS ((char *, struct obstack *));
+
+static struct type *
+lookup_utype PARAMS ((DIE_REF));
+
+static struct type *
+alloc_utype PARAMS ((DIE_REF, struct type *));
+
+static struct symbol *
+new_symbol PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+synthesize_typedef PARAMS ((struct dieinfo *, struct objfile *,
+ struct type *));
+
+static int
+locval PARAMS ((char *));
+
+static void
+set_cu_language PARAMS ((struct dieinfo *));
+
+static struct type *
+dwarf_fundamental_type PARAMS ((struct objfile *, int));
+
+
+/*
+
+LOCAL FUNCTION
+
+ dwarf_fundamental_type -- lookup or create a fundamental type
+
+SYNOPSIS
+
+ struct type *
+ dwarf_fundamental_type (struct objfile *objfile, int typeid)
+
+DESCRIPTION
+
+ DWARF version 1 doesn't supply any fundamental type information,
+ so gdb has to construct such types. It has a fixed number of
+ fundamental types that it knows how to construct, which is the
+ union of all types that it knows how to construct for all languages
+ that it knows about. These are enumerated in gdbtypes.h.
+
+ As an example, assume we find a DIE that references a DWARF
+ fundamental type of FT_integer. We first look in the ftypes
+ array to see if we already have such a type, indexed by the
+ gdb internal value of FT_INTEGER. If so, we simply return a
+ pointer to that type. If not, then we ask an appropriate
+ language dependent routine to create a type FT_INTEGER, using
+ defaults reasonable for the current target machine, and install
+ that type in ftypes for future reference.
+
+RETURNS
+
+ Pointer to a fundamental type.
+
+*/
+
+static struct type *
+dwarf_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
+ {
+ error ("internal error - invalid fundamental type id %d", typeid);
+ }
+
+ /* Look for this particular type in the fundamental type vector. If one is
+ not found, create and install one appropriate for the current language
+ and the current target machine. */
+
+ if (ftypes[typeid] == NULL)
+ {
+ ftypes[typeid] = cu_language_defn -> la_fund_type(objfile, typeid);
+ }
+
+ return (ftypes[typeid]);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ set_cu_language -- set local copy of language for compilation unit
+
+SYNOPSIS
+
+ void
+ set_cu_language (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Decode the language attribute for a compilation unit DIE and
+ remember what the language was. We use this at various times
+ when processing DIE's for a given compilation unit.
+
+RETURNS
+
+ No return value.
+
+ */
+
+static void
+set_cu_language (dip)
+ struct dieinfo *dip;
+{
+ switch (dip -> at_language)
+ {
+ case LANG_C89:
+ case LANG_C:
+ cu_language = language_c;
+ break;
+ case LANG_C_PLUS_PLUS:
+ cu_language = language_cplus;
+ break;
+ case LANG_CHILL:
+ cu_language = language_chill;
+ break;
+ case LANG_MODULA2:
+ cu_language = language_m2;
+ break;
+ case LANG_ADA83:
+ case LANG_COBOL74:
+ case LANG_COBOL85:
+ case LANG_FORTRAN77:
+ case LANG_FORTRAN90:
+ case LANG_PASCAL83:
+ /* We don't know anything special about these yet. */
+ cu_language = language_unknown;
+ break;
+ default:
+ /* If no at_language, try to deduce one from the filename */
+ cu_language = deduce_language_from_filename (dip -> at_name);
+ break;
+ }
+ cu_language_defn = language_def (cu_language);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ dwarf_build_psymtabs -- build partial symtabs from DWARF debug info
+
+SYNOPSIS
+
+ void dwarf_build_psymtabs (struct objfile *objfile,
+ struct section_offsets *section_offsets,
+ int mainline, file_ptr dbfoff, unsigned int dbfsize,
+ file_ptr lnoffset, unsigned int lnsize)
+
+DESCRIPTION
+
+ This function is called upon to build partial symtabs from files
+ containing DIE's (Dwarf Information Entries) and DWARF line numbers.
+
+ It is passed a bfd* containing the DIES
+ and line number information, the corresponding filename for that
+ file, a base address for relocating the symbols, a flag indicating
+ whether or not this debugging information is from a "main symbol
+ table" rather than a shared library or dynamically linked file,
+ and file offset/size pairs for the DIE information and line number
+ information.
+
+RETURNS
+
+ No return value.
+
+ */
+
+void
+dwarf_build_psymtabs (objfile, section_offsets, mainline, dbfoff, dbfsize,
+ lnoffset, lnsize)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+ file_ptr dbfoff;
+ unsigned int dbfsize;
+ file_ptr lnoffset;
+ unsigned int lnsize;
+{
+ bfd *abfd = objfile->obfd;
+ struct cleanup *back_to;
+
+ current_objfile = objfile;
+ dbsize = dbfsize;
+ dbbase = xmalloc (dbsize);
+ dbroff = 0;
+ if ((bfd_seek (abfd, dbfoff, L_SET) != 0) ||
+ (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
+ {
+ free (dbbase);
+ error ("can't read DWARF data from '%s'", bfd_get_filename (abfd));
+ }
+ back_to = make_cleanup (free, dbbase);
+
+ /* If we are reinitializing, or if we have never loaded syms yet, init.
+ Since we have no idea how many DIES we are looking at, we just guess
+ some arbitrary value. */
+
+ if (mainline || objfile -> global_psymbols.size == 0 ||
+ objfile -> static_psymbols.size == 0)
+ {
+ init_psymbol_list (objfile, 1024);
+ }
+
+ /* Save the relocation factor where everybody can see it. */
+
+ base_section_offsets = section_offsets;
+ baseaddr = ANOFFSET (section_offsets, 0);
+
+ /* Follow the compilation unit sibling chain, building a partial symbol
+ table entry for each one. Save enough information about each compilation
+ unit to locate the full DWARF information later. */
+
+ scan_compilation_units (dbbase, dbbase + dbsize, dbfoff, lnoffset, objfile);
+
+ do_cleanups (back_to);
+ current_objfile = NULL;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_lexical_block_scope -- process all dies in a lexical block
+
+SYNOPSIS
+
+ static void read_lexical_block_scope (struct dieinfo *dip,
+ char *thisdie, char *enddie)
+
+DESCRIPTION
+
+ Process all the DIES contained within a lexical block scope.
+ Start a new scope, process the dies, and then close the scope.
+
+ */
+
+static void
+read_lexical_block_scope (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ register struct context_stack *new;
+
+ push_context (0, dip -> at_low_pc);
+ process_dies (thisdie + dip -> die_length, enddie, objfile);
+ new = pop_context ();
+ if (local_symbols != NULL)
+ {
+ finish_block (0, &local_symbols, new -> old_blocks, new -> start_addr,
+ dip -> at_high_pc, objfile);
+ }
+ local_symbols = new -> locals;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ lookup_utype -- look up a user defined type from die reference
+
+SYNOPSIS
+
+ static type *lookup_utype (DIE_REF die_ref)
+
+DESCRIPTION
+
+ Given a DIE reference, lookup the user defined type associated with
+ that DIE, if it has been registered already. If not registered, then
+ return NULL. Alloc_utype() can be called to register an empty
+ type for this reference, which will be filled in later when the
+ actual referenced DIE is processed.
+ */
+
+static struct type *
+lookup_utype (die_ref)
+ DIE_REF die_ref;
+{
+ struct type *type = NULL;
+ int utypeidx;
+
+ utypeidx = (die_ref - dbroff) / 4;
+ if ((utypeidx < 0) || (utypeidx >= numutypes))
+ {
+ complain (&bad_die_ref, DIE_ID, DIE_NAME);
+ }
+ else
+ {
+ type = *(utypes + utypeidx);
+ }
+ return (type);
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ alloc_utype -- add a user defined type for die reference
+
+SYNOPSIS
+
+ static type *alloc_utype (DIE_REF die_ref, struct type *utypep)
+
+DESCRIPTION
+
+ Given a die reference DIE_REF, and a possible pointer to a user
+ defined type UTYPEP, register that this reference has a user
+ defined type and either use the specified type in UTYPEP or
+ make a new empty type that will be filled in later.
+
+ We should only be called after calling lookup_utype() to verify that
+ there is not currently a type registered for DIE_REF.
+ */
+
+static struct type *
+alloc_utype (die_ref, utypep)
+ DIE_REF die_ref;
+ struct type *utypep;
+{
+ struct type **typep;
+ int utypeidx;
+
+ utypeidx = (die_ref - dbroff) / 4;
+ typep = utypes + utypeidx;
+ if ((utypeidx < 0) || (utypeidx >= numutypes))
+ {
+ utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ complain (&bad_die_ref, DIE_ID, DIE_NAME);
+ }
+ else if (*typep != NULL)
+ {
+ utypep = *typep;
+ complain (&dup_user_type_allocation, DIE_ID, DIE_NAME);
+ }
+ else
+ {
+ if (utypep == NULL)
+ {
+ utypep = alloc_type (current_objfile);
+ }
+ *typep = utypep;
+ }
+ return (utypep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_die_type -- return a type for a specified die
+
+SYNOPSIS
+
+ static struct type *decode_die_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Given a pointer to a die information structure DIP, decode the
+ type of the die and return a pointer to the decoded type. All
+ dies without specific types default to type int.
+ */
+
+static struct type *
+decode_die_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *type = NULL;
+
+ if (dip -> at_fund_type != 0)
+ {
+ type = decode_fund_type (dip -> at_fund_type);
+ }
+ else if (dip -> at_mod_fund_type != NULL)
+ {
+ type = decode_mod_fund_type (dip -> at_mod_fund_type);
+ }
+ else if (dip -> at_user_def_type)
+ {
+ if ((type = lookup_utype (dip -> at_user_def_type)) == NULL)
+ {
+ type = alloc_utype (dip -> at_user_def_type, NULL);
+ }
+ }
+ else if (dip -> at_mod_u_d_type)
+ {
+ type = decode_mod_u_d_type (dip -> at_mod_u_d_type);
+ }
+ else
+ {
+ type = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ }
+ return (type);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ struct_type -- compute and return the type for a struct or union
+
+SYNOPSIS
+
+ static struct type *struct_type (struct dieinfo *dip, char *thisdie,
+ char *enddie, struct objfile *objfile)
+
+DESCRIPTION
+
+ Given pointer to a die information structure for a die which
+ defines a union or structure (and MUST define one or the other),
+ and pointers to the raw die data that define the range of dies which
+ define the members, compute and return the user defined type for the
+ structure or union.
+ */
+
+static struct type *
+struct_type (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct nextfield {
+ struct nextfield *next;
+ struct field field;
+ };
+ struct nextfield *list = NULL;
+ struct nextfield *new;
+ int nfields = 0;
+ int n;
+ struct dieinfo mbr;
+ char *nextdie;
+#if !BITS_BIG_ENDIAN
+ int anonymous_size;
+#endif
+
+ if ((type = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ /* No forward references created an empty type, so install one now */
+ type = alloc_utype (dip -> die_ref, NULL);
+ }
+ INIT_CPLUS_SPECIFIC(type);
+ switch (dip -> die_tag)
+ {
+ case TAG_class_type:
+ TYPE_CODE (type) = TYPE_CODE_CLASS;
+ break;
+ case TAG_structure_type:
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ break;
+ case TAG_union_type:
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ break;
+ default:
+ /* Should never happen */
+ TYPE_CODE (type) = TYPE_CODE_UNDEF;
+ complain (&missing_tag, DIE_ID, DIE_NAME);
+ break;
+ }
+ /* Some compilers try to be helpful by inventing "fake" names for
+ anonymous enums, structures, and unions, like "~0fake" or ".0fake".
+ Thanks, but no thanks... */
+ if (dip -> at_name != NULL
+ && *dip -> at_name != '~'
+ && *dip -> at_name != '.')
+ {
+ TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack,
+ "", "", dip -> at_name);
+ }
+ /* Use whatever size is known. Zero is a valid size. We might however
+ wish to check has_at_byte_size to make sure that some byte size was
+ given explicitly, but DWARF doesn't specify that explicit sizes of
+ zero have to present, so complaining about missing sizes should
+ probably not be the default. */
+ TYPE_LENGTH (type) = dip -> at_byte_size;
+ thisdie += dip -> die_length;
+ while (thisdie < enddie)
+ {
+ basicdieinfo (&mbr, thisdie, objfile);
+ completedieinfo (&mbr, objfile);
+ if (mbr.die_length <= SIZEOF_DIE_LENGTH)
+ {
+ break;
+ }
+ else if (mbr.at_sibling != 0)
+ {
+ nextdie = dbbase + mbr.at_sibling - dbroff;
+ }
+ else
+ {
+ nextdie = thisdie + mbr.die_length;
+ }
+ switch (mbr.die_tag)
+ {
+ case TAG_member:
+ /* 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 =
+ obsavestring (mbr.at_name, strlen (mbr.at_name),
+ &objfile -> type_obstack);
+ list -> field.type = decode_die_type (&mbr);
+ list -> field.bitpos = 8 * locval (mbr.at_location);
+ /* Handle bit fields. */
+ list -> field.bitsize = mbr.at_bit_size;
+#if BITS_BIG_ENDIAN
+ /* For big endian bits, the at_bit_offset gives the additional
+ bit offset from the MSB of the containing anonymous object to
+ the MSB of the field. We don't have to do anything special
+ since we don't need to know the size of the anonymous object. */
+ list -> field.bitpos += mbr.at_bit_offset;
+#else
+ /* For little endian bits, we need to have a non-zero at_bit_size,
+ so that we know we are in fact dealing with a bitfield. Compute
+ the bit offset to the MSB of the anonymous object, subtract off
+ the number of bits from the MSB of the field to the MSB of the
+ object, and then subtract off the number of bits of the field
+ itself. The result is the bit offset of the LSB of the field. */
+ if (mbr.at_bit_size > 0)
+ {
+ if (mbr.has_at_byte_size)
+ {
+ /* The size of the anonymous object containing the bit field
+ is explicit, so use the indicated size (in bytes). */
+ anonymous_size = mbr.at_byte_size;
+ }
+ else
+ {
+ /* The size of the anonymous object containing the bit field
+ matches the size of an object of the bit field's type.
+ DWARF allows at_byte_size to be left out in such cases,
+ as a debug information size optimization. */
+ anonymous_size = TYPE_LENGTH (list -> field.type);
+ }
+ list -> field.bitpos +=
+ anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
+ }
+#endif
+ nfields++;
+ break;
+ default:
+ process_dies (thisdie, nextdie, objfile);
+ break;
+ }
+ thisdie = nextdie;
+ }
+ /* Now create the vector of fields, and record how big it is. We may
+ not even have any fields, if this DIE was generated due to a reference
+ to an anonymous structure or union. In this case, TYPE_FLAG_STUB is
+ set, which clues gdb in to the fact that it needs to search elsewhere
+ for the full structure definition. */
+ if (nfields == 0)
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ }
+ else
+ {
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, 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);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_structure_scope -- process all dies within struct or union
+
+SYNOPSIS
+
+ static void read_structure_scope (struct dieinfo *dip,
+ char *thisdie, char *enddie, struct objfile *objfile)
+
+DESCRIPTION
+
+ Called when we find the DIE that starts a structure or union
+ scope (definition) to process all dies that define the members
+ of the structure or union. DIP is a pointer to the die info
+ struct for the DIE that names the structure or union.
+
+NOTES
+
+ Note that we need to call struct_type regardless of whether or not
+ the DIE has an at_name attribute, since it might be an anonymous
+ structure or union. This gets the type entered into our set of
+ user defined types.
+
+ However, if the structure is incomplete (an opaque struct/union)
+ then suppress creating a symbol table entry for it since gdb only
+ wants to find the one with the complete definition. Note that if
+ it is complete, we just call new_symbol, which does it's own
+ checking about whether the struct/union is anonymous or not (and
+ suppresses creating a symbol table entry itself).
+
+ */
+
+static void
+read_structure_scope (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct symbol *sym;
+
+ type = struct_type (dip, thisdie, enddie, objfile);
+ if (!(TYPE_FLAGS (type) & TYPE_FLAG_STUB))
+ {
+ sym = new_symbol (dip, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_TYPE (sym) = type;
+ if (cu_language == language_cplus)
+ {
+ synthesize_typedef (dip, objfile, type);
+ }
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_array_element_type -- decode type of the array elements
+
+SYNOPSIS
+
+ static struct type *decode_array_element_type (char *scan, char *end)
+
+DESCRIPTION
+
+ As the last step in decoding the array subscript information for an
+ array DIE, we need to decode the type of the array elements. We are
+ passed a pointer to this last part of the subscript information and
+ must return the appropriate type. If the type attribute is not
+ recognized, just warn about the problem and return type int.
+ */
+
+static struct type *
+decode_array_element_type (scan)
+ char *scan;
+{
+ struct type *typep;
+ DIE_REF die_ref;
+ unsigned short attribute;
+ unsigned short fundtype;
+ int nbytes;
+
+ attribute = target_to_host (scan, SIZEOF_ATTRIBUTE, GET_UNSIGNED,
+ current_objfile);
+ scan += SIZEOF_ATTRIBUTE;
+ if ((nbytes = attribute_size (attribute)) == -1)
+ {
+ complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ }
+ else
+ {
+ switch (attribute)
+ {
+ case AT_fund_type:
+ fundtype = target_to_host (scan, nbytes, GET_UNSIGNED,
+ current_objfile);
+ typep = decode_fund_type (fundtype);
+ break;
+ case AT_mod_fund_type:
+ typep = decode_mod_fund_type (scan);
+ break;
+ case AT_user_def_type:
+ die_ref = target_to_host (scan, nbytes, GET_UNSIGNED,
+ current_objfile);
+ if ((typep = lookup_utype (die_ref)) == NULL)
+ {
+ typep = alloc_utype (die_ref, NULL);
+ }
+ break;
+ case AT_mod_u_d_type:
+ typep = decode_mod_u_d_type (scan);
+ break;
+ default:
+ complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ break;
+ }
+ }
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_subscript_data_item -- decode array subscript item
+
+SYNOPSIS
+
+ static struct type *
+ decode_subscript_data_item (char *scan, char *end)
+
+DESCRIPTION
+
+ The array subscripts and the data type of the elements of an
+ array are described by a list of data items, stored as a block
+ of contiguous bytes. There is a data item describing each array
+ dimension, and a final data item describing the element type.
+ The data items are ordered the same as their appearance in the
+ source (I.E. leftmost dimension first, next to leftmost second,
+ etc).
+
+ The data items describing each array dimension consist of four
+ parts: (1) a format specifier, (2) type type of the subscript
+ index, (3) a description of the low bound of the array dimension,
+ and (4) a description of the high bound of the array dimension.
+
+ The last data item is the description of the type of each of
+ the array elements.
+
+ We are passed a pointer to the start of the block of bytes
+ containing the remaining data items, and a pointer to the first
+ byte past the data. This function recursively decodes the
+ remaining data items and returns a type.
+
+ If we somehow fail to decode some data, we complain about it
+ and return a type "array of int".
+
+BUGS
+ FIXME: This code only implements the forms currently used
+ by the AT&T and GNU C compilers.
+
+ The end pointer is supplied for error checking, maybe we should
+ use it for that...
+ */
+
+static struct type *
+decode_subscript_data_item (scan, end)
+ char *scan;
+ char *end;
+{
+ struct type *typep = NULL; /* Array type we are building */
+ struct type *nexttype; /* Type of each element (may be array) */
+ struct type *indextype; /* Type of this index */
+ struct type *rangetype;
+ unsigned int format;
+ unsigned short fundtype;
+ unsigned long lowbound;
+ unsigned long highbound;
+ int nbytes;
+
+ format = target_to_host (scan, SIZEOF_FORMAT_SPECIFIER, GET_UNSIGNED,
+ current_objfile);
+ scan += SIZEOF_FORMAT_SPECIFIER;
+ switch (format)
+ {
+ case FMT_ET:
+ typep = decode_array_element_type (scan);
+ break;
+ case FMT_FT_C_C:
+ fundtype = target_to_host (scan, SIZEOF_FMT_FT, GET_UNSIGNED,
+ current_objfile);
+ indextype = decode_fund_type (fundtype);
+ scan += SIZEOF_FMT_FT;
+ nbytes = TARGET_FT_LONG_SIZE (current_objfile);
+ lowbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile);
+ scan += nbytes;
+ highbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile);
+ scan += nbytes;
+ nexttype = decode_subscript_data_item (scan, end);
+ if (nexttype == NULL)
+ {
+ /* Munged subscript data or other problem, fake it. */
+ complain (&subscript_data_items, DIE_ID, DIE_NAME);
+ nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ }
+ rangetype = create_range_type ((struct type *) NULL, indextype,
+ lowbound, highbound);
+ typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
+ break;
+ case FMT_FT_C_X:
+ case FMT_FT_X_C:
+ case FMT_FT_X_X:
+ case FMT_UT_C_C:
+ case FMT_UT_C_X:
+ case FMT_UT_X_C:
+ case FMT_UT_X_X:
+ complain (&unhandled_array_subscript_format, DIE_ID, DIE_NAME, format);
+ nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0);
+ typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
+ break;
+ default:
+ complain (&unknown_array_subscript_format, DIE_ID, DIE_NAME, format);
+ nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0);
+ typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
+ break;
+ }
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ dwarf_read_array_type -- read TAG_array_type DIE
+
+SYNOPSIS
+
+ static void dwarf_read_array_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Extract all information from a TAG_array_type DIE and add to
+ the user defined type vector.
+ */
+
+static void
+dwarf_read_array_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *type;
+ struct type *utype;
+ char *sub;
+ char *subend;
+ unsigned short blocksz;
+ int nbytes;
+
+ if (dip -> at_ordering != ORD_row_major)
+ {
+ /* FIXME: Can gdb even handle column major arrays? */
+ complain (&not_row_major, DIE_ID, DIE_NAME);
+ }
+ if ((sub = dip -> at_subscr_data) != NULL)
+ {
+ nbytes = attribute_size (AT_subscr_data);
+ blocksz = target_to_host (sub, nbytes, GET_UNSIGNED, current_objfile);
+ subend = sub + nbytes + blocksz;
+ sub += nbytes;
+ type = decode_subscript_data_item (sub, subend);
+ if ((utype = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ /* Install user defined type that has not been referenced yet. */
+ alloc_utype (dip -> die_ref, type);
+ }
+ else if (TYPE_CODE (utype) == TYPE_CODE_UNDEF)
+ {
+ /* Ick! A forward ref has already generated a blank type in our
+ slot, and this type probably already has things pointing to it
+ (which is what caused it to be created in the first place).
+ If it's just a place holder we can plop our fully defined type
+ on top of it. We can't recover the space allocated for our
+ new type since it might be on an obstack, but we could reuse
+ it if we kept a list of them, but it might not be worth it
+ (FIXME). */
+ *utype = *type;
+ }
+ else
+ {
+ /* Double ick! Not only is a type already in our slot, but
+ someone has decorated it. Complain and leave it alone. */
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_tag_pointer_type -- read TAG_pointer_type DIE
+
+SYNOPSIS
+
+ static void read_tag_pointer_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Extract all information from a TAG_pointer_type DIE and add to
+ the user defined type vector.
+ */
+
+static void
+read_tag_pointer_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *type;
+ struct type *utype;
+
+ type = decode_die_type (dip);
+ if ((utype = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ utype = lookup_pointer_type (type);
+ alloc_utype (dip -> die_ref, utype);
+ }
+ else
+ {
+ TYPE_TARGET_TYPE (utype) = type;
+ TYPE_POINTER_TYPE (type) = utype;
+
+ /* We assume the machine has only one representation for pointers! */
+ /* FIXME: This confuses host<->target data representations, and is a
+ poor assumption besides. */
+
+ TYPE_LENGTH (utype) = sizeof (char *);
+ TYPE_CODE (utype) = TYPE_CODE_PTR;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_tag_string_type -- read TAG_string_type DIE
+
+SYNOPSIS
+
+ static void read_tag_string_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Extract all information from a TAG_string_type DIE and add to
+ the user defined type vector. It isn't really a user defined
+ type, but it behaves like one, with other DIE's using an
+ AT_user_def_type attribute to reference it.
+ */
+
+static void
+read_tag_string_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *utype;
+ struct type *indextype;
+ struct type *rangetype;
+ unsigned long lowbound = 0;
+ unsigned long highbound;
+
+ if (dip -> has_at_byte_size)
+ {
+ /* A fixed bounds string */
+ highbound = dip -> at_byte_size - 1;
+ }
+ else
+ {
+ /* A varying length string. Stub for now. (FIXME) */
+ highbound = 1;
+ }
+ indextype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ rangetype = create_range_type ((struct type *) NULL, indextype, lowbound,
+ highbound);
+
+ utype = lookup_utype (dip -> die_ref);
+ if (utype == NULL)
+ {
+ /* No type defined, go ahead and create a blank one to use. */
+ utype = alloc_utype (dip -> die_ref, (struct type *) NULL);
+ }
+ else
+ {
+ /* Already a type in our slot due to a forward reference. Make sure it
+ is a blank one. If not, complain and leave it alone. */
+ if (TYPE_CODE (utype) != TYPE_CODE_UNDEF)
+ {
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+ return;
+ }
+ }
+
+ /* Create the string type using the blank type we either found or created. */
+ utype = create_string_type (utype, rangetype);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_subroutine_type -- process TAG_subroutine_type dies
+
+SYNOPSIS
+
+ static void read_subroutine_type (struct dieinfo *dip, char thisdie,
+ char *enddie)
+
+DESCRIPTION
+
+ Handle DIES due to C code like:
+
+ struct foo {
+ int (*funcp)(int a, long l); (Generates TAG_subroutine_type DIE)
+ int b;
+ };
+
+NOTES
+
+ The parameter DIES are currently ignored. See if gdb has a way to
+ include this info in it's type system, and decode them if so. Is
+ this what the type structure's "arg_types" field is for? (FIXME)
+ */
+
+static void
+read_subroutine_type (dip, thisdie, enddie)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+{
+ struct type *type; /* Type that this function returns */
+ struct type *ftype; /* Function that returns above type */
+
+ /* Decode the type that this subroutine returns */
+
+ type = decode_die_type (dip);
+
+ /* Check to see if we already have a partially constructed user
+ defined type for this DIE, from a forward reference. */
+
+ if ((ftype = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ /* This is the first reference to one of these types. Make
+ a new one and place it in the user defined types. */
+ ftype = lookup_function_type (type);
+ alloc_utype (dip -> die_ref, ftype);
+ }
+ else if (TYPE_CODE (ftype) == TYPE_CODE_UNDEF)
+ {
+ /* We have an existing partially constructed type, so bash it
+ into the correct type. */
+ TYPE_TARGET_TYPE (ftype) = type;
+ TYPE_FUNCTION_TYPE (type) = ftype;
+ TYPE_LENGTH (ftype) = 1;
+ TYPE_CODE (ftype) = TYPE_CODE_FUNC;
+ }
+ else
+ {
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_enumeration -- process dies which define an enumeration
+
+SYNOPSIS
+
+ static void read_enumeration (struct dieinfo *dip, char *thisdie,
+ char *enddie, struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to a die which begins an enumeration, process all
+ the dies that define the members of the enumeration.
+
+NOTES
+
+ Note that we need to call enum_type regardless of whether or not we
+ have a symbol, since we might have an enum without a tag name (thus
+ no symbol for the tagname).
+ */
+
+static void
+read_enumeration (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct symbol *sym;
+
+ type = enum_type (dip, objfile);
+ sym = new_symbol (dip, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_TYPE (sym) = type;
+ if (cu_language == language_cplus)
+ {
+ synthesize_typedef (dip, objfile, type);
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ enum_type -- decode and return a type for an enumeration
+
+SYNOPSIS
+
+ static type *enum_type (struct dieinfo *dip, struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to a die information structure for the die which
+ starts an enumeration, process all the dies that define the members
+ of the enumeration and return a type pointer for the enumeration.
+
+ At the same time, for each member of the enumeration, create a
+ symbol for it with namespace VAR_NAMESPACE and class LOC_CONST,
+ and give it the type of the enumeration itself.
+
+NOTES
+
+ Note that the DWARF specification explicitly mandates that enum
+ constants occur in reverse order from the source program order,
+ for "consistency" and because this ordering is easier for many
+ compilers to generate. (Draft 6, sec 3.8.5, Enumeration type
+ Entries). Because gdb wants to see the enum members in program
+ source order, we have to ensure that the order gets reversed while
+ we are processing them.
+ */
+
+static struct type *
+enum_type (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct nextfield {
+ struct nextfield *next;
+ struct field field;
+ };
+ struct nextfield *list = NULL;
+ struct nextfield *new;
+ int nfields = 0;
+ int n;
+ char *scan;
+ char *listend;
+ unsigned short blocksz;
+ struct symbol *sym;
+ int nbytes;
+
+ if ((type = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ /* No forward references created an empty type, so install one now */
+ type = alloc_utype (dip -> die_ref, NULL);
+ }
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ /* Some compilers try to be helpful by inventing "fake" names for
+ anonymous enums, structures, and unions, like "~0fake" or ".0fake".
+ Thanks, but no thanks... */
+ if (dip -> at_name != NULL
+ && *dip -> at_name != '~'
+ && *dip -> at_name != '.')
+ {
+ TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack,
+ "", "", dip -> at_name);
+ }
+ if (dip -> at_byte_size != 0)
+ {
+ TYPE_LENGTH (type) = dip -> at_byte_size;
+ }
+ if ((scan = dip -> at_element_list) != NULL)
+ {
+ if (dip -> short_element_list)
+ {
+ nbytes = attribute_size (AT_short_element_list);
+ }
+ else
+ {
+ nbytes = attribute_size (AT_element_list);
+ }
+ blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile);
+ listend = scan + nbytes + blocksz;
+ scan += nbytes;
+ while (scan < listend)
+ {
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new -> next = list;
+ list = new;
+ list -> field.type = NULL;
+ list -> field.bitsize = 0;
+ list -> field.bitpos =
+ target_to_host (scan, TARGET_FT_LONG_SIZE (objfile), GET_SIGNED,
+ objfile);
+ scan += TARGET_FT_LONG_SIZE (objfile);
+ list -> field.name = obsavestring (scan, strlen (scan),
+ &objfile -> type_obstack);
+ scan += strlen (scan) + 1;
+ nfields++;
+ /* Handcraft a new symbol for this enum member. */
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = create_name (list -> field.name,
+ &objfile->symbol_obstack);
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_VALUE (sym) = list -> field.bitpos;
+ add_symbol_to_list (sym, list_in_scope);
+ }
+ /* Now create the vector of fields, and record how big it is. This is
+ where we reverse the order, by pulling the members off the list in
+ reverse order from how they were inserted. If we have no fields
+ (this is apparently possible in C++) then skip building a field
+ vector. */
+ if (nfields > 0)
+ {
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) * nfields);
+ /* Copy the saved-up fields into the field vector. */
+ for (n = 0; (n < nfields) && (list != NULL); list = list -> next)
+ {
+ TYPE_FIELD (type, n++) = list -> field;
+ }
+ }
+ }
+ return (type);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_func_scope -- process all dies within a function scope
+
+DESCRIPTION
+
+ Process all dies within a given function scope. We are passed
+ a die information structure pointer DIP for the die which
+ starts the function scope, and pointers into the raw die data
+ that define the dies within the function scope.
+
+ For now, we ignore lexical block scopes within the function.
+ The problem is that AT&T cc does not define a DWARF lexical
+ block scope for the function itself, while gcc defines a
+ lexical block scope for the function. We need to think about
+ how to handle this difference, or if it is even a problem.
+ (FIXME)
+ */
+
+static void
+read_func_scope (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ register struct context_stack *new;
+
+ if (objfile -> ei.entry_point >= dip -> at_low_pc &&
+ objfile -> ei.entry_point < dip -> at_high_pc)
+ {
+ objfile -> ei.entry_func_lowpc = dip -> at_low_pc;
+ objfile -> ei.entry_func_highpc = dip -> at_high_pc;
+ }
+ if (STREQ (dip -> at_name, "main")) /* FIXME: hardwired name */
+ {
+ objfile -> ei.main_func_lowpc = dip -> at_low_pc;
+ objfile -> ei.main_func_highpc = dip -> at_high_pc;
+ }
+ new = push_context (0, dip -> at_low_pc);
+ new -> name = new_symbol (dip, objfile);
+ list_in_scope = &local_symbols;
+ process_dies (thisdie + dip -> die_length, enddie, objfile);
+ new = pop_context ();
+ /* Make a block for the local symbols within. */
+ finish_block (new -> name, &local_symbols, new -> old_blocks,
+ new -> start_addr, dip -> at_high_pc, objfile);
+ list_in_scope = &file_symbols;
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ handle_producer -- process the AT_producer attribute
+
+DESCRIPTION
+
+ Perform any operations that depend on finding a particular
+ AT_producer attribute.
+
+ */
+
+static void
+handle_producer (producer)
+ char *producer;
+{
+
+ /* If this compilation unit was compiled with g++ or gcc, then set the
+ processing_gcc_compilation flag. */
+
+ processing_gcc_compilation =
+ STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
+ || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER))
+ || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+
+ /* Select a demangling style if we can identify the producer and if
+ the current style is auto. We leave the current style alone if it
+ is not auto. We also leave the demangling style alone if we find a
+ gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
+
+ if (AUTO_DEMANGLING)
+ {
+ if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+ else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER)))
+ {
+ set_demangling_style (LUCID_DEMANGLING_STYLE_STRING);
+ }
+ }
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ read_file_scope -- process all dies within a file scope
+
+DESCRIPTION
+
+ Process all dies within a given file scope. We are passed a
+ pointer to the die information structure for the die which
+ starts the file scope, and pointers into the raw die data which
+ mark the range of dies within the file scope.
+
+ When the partial symbol table is built, the file offset for the line
+ number table for each compilation unit is saved in the partial symbol
+ table entry for that compilation unit. As the symbols for each
+ compilation unit are read, the line number table is read into memory
+ and the variable lnbase is set to point to it. Thus all we have to
+ do is use lnbase to access the line number table for the current
+ compilation unit.
+ */
+
+static void
+read_file_scope (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ struct cleanup *back_to;
+ struct symtab *symtab;
+
+ if (objfile -> ei.entry_point >= dip -> at_low_pc &&
+ objfile -> ei.entry_point < dip -> at_high_pc)
+ {
+ objfile -> ei.entry_file_lowpc = dip -> at_low_pc;
+ objfile -> ei.entry_file_highpc = dip -> at_high_pc;
+ }
+ set_cu_language (dip);
+ if (dip -> at_producer != NULL)
+ {
+ handle_producer (dip -> at_producer);
+ }
+ numutypes = (enddie - thisdie) / 4;
+ utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *));
+ back_to = make_cleanup (free, utypes);
+ memset (utypes, 0, numutypes * sizeof (struct type *));
+ memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
+ start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc);
+ decode_line_numbers (lnbase);
+ process_dies (thisdie + dip -> die_length, enddie, objfile);
+
+ symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile, 0);
+ if (symtab != NULL)
+ {
+ symtab -> language = cu_language;
+ }
+ do_cleanups (back_to);
+ utypes = NULL;
+ numutypes = 0;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ process_dies -- process a range of DWARF Information Entries
+
+SYNOPSIS
+
+ static void process_dies (char *thisdie, char *enddie,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Process all DIE's in a specified range. May be (and almost
+ certainly will be) called recursively.
+ */
+
+static void
+process_dies (thisdie, enddie, objfile)
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ char *nextdie;
+ struct dieinfo di;
+
+ while (thisdie < enddie)
+ {
+ basicdieinfo (&di, thisdie, objfile);
+ if (di.die_length < SIZEOF_DIE_LENGTH)
+ {
+ break;
+ }
+ else if (di.die_tag == TAG_padding)
+ {
+ nextdie = thisdie + di.die_length;
+ }
+ else
+ {
+ completedieinfo (&di, objfile);
+ if (di.at_sibling != 0)
+ {
+ nextdie = dbbase + di.at_sibling - dbroff;
+ }
+ else
+ {
+ nextdie = thisdie + di.die_length;
+ }
+ switch (di.die_tag)
+ {
+ case TAG_compile_unit:
+ read_file_scope (&di, thisdie, nextdie, objfile);
+ break;
+ case TAG_global_subroutine:
+ case TAG_subroutine:
+ if (di.has_at_low_pc)
+ {
+ read_func_scope (&di, thisdie, nextdie, objfile);
+ }
+ break;
+ case TAG_lexical_block:
+ read_lexical_block_scope (&di, thisdie, nextdie, objfile);
+ break;
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ read_structure_scope (&di, thisdie, nextdie, objfile);
+ break;
+ case TAG_enumeration_type:
+ read_enumeration (&di, thisdie, nextdie, objfile);
+ break;
+ case TAG_subroutine_type:
+ read_subroutine_type (&di, thisdie, nextdie);
+ break;
+ case TAG_array_type:
+ dwarf_read_array_type (&di);
+ break;
+ case TAG_pointer_type:
+ read_tag_pointer_type (&di);
+ break;
+ case TAG_string_type:
+ read_tag_string_type (&di);
+ break;
+ default:
+ new_symbol (&di, objfile);
+ break;
+ }
+ }
+ thisdie = nextdie;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_line_numbers -- decode a line number table fragment
+
+SYNOPSIS
+
+ static void decode_line_numbers (char *tblscan, char *tblend,
+ long length, long base, long line, long pc)
+
+DESCRIPTION
+
+ Translate the DWARF line number information to gdb form.
+
+ The ".line" section contains one or more line number tables, one for
+ each ".line" section from the objects that were linked.
+
+ The AT_stmt_list attribute for each TAG_source_file entry in the
+ ".debug" section contains the offset into the ".line" section for the
+ start of the table for that file.
+
+ The table itself has the following structure:
+
+ <table length><base address><source statement entry>
+ 4 bytes 4 bytes 10 bytes
+
+ The table length is the total size of the table, including the 4 bytes
+ for the length information.
+
+ The base address is the address of the first instruction generated
+ for the source file.
+
+ Each source statement entry has the following structure:
+
+ <line number><statement position><address delta>
+ 4 bytes 2 bytes 4 bytes
+
+ The line number is relative to the start of the file, starting with
+ line 1.
+
+ The statement position either -1 (0xFFFF) or the number of characters
+ from the beginning of the line to the beginning of the statement.
+
+ The address delta is the difference between the base address and
+ the address of the first instruction for the statement.
+
+ Note that we must copy the bytes from the packed table to our local
+ variables before attempting to use them, to avoid alignment problems
+ on some machines, particularly RISC processors.
+
+BUGS
+
+ Does gdb expect the line numbers to be sorted? They are now by
+ chance/luck, but are not required to be. (FIXME)
+
+ The line with number 0 is unused, gdb apparently can discover the
+ span of the last line some other way. How? (FIXME)
+ */
+
+static void
+decode_line_numbers (linetable)
+ char *linetable;
+{
+ char *tblscan;
+ char *tblend;
+ unsigned long length;
+ unsigned long base;
+ unsigned long line;
+ unsigned long pc;
+
+ if (linetable != NULL)
+ {
+ tblscan = tblend = linetable;
+ length = target_to_host (tblscan, SIZEOF_LINETBL_LENGTH, GET_UNSIGNED,
+ current_objfile);
+ tblscan += SIZEOF_LINETBL_LENGTH;
+ tblend += length;
+ base = target_to_host (tblscan, TARGET_FT_POINTER_SIZE (objfile),
+ GET_UNSIGNED, current_objfile);
+ tblscan += TARGET_FT_POINTER_SIZE (objfile);
+ base += baseaddr;
+ while (tblscan < tblend)
+ {
+ line = target_to_host (tblscan, SIZEOF_LINETBL_LINENO, GET_UNSIGNED,
+ current_objfile);
+ tblscan += SIZEOF_LINETBL_LINENO + SIZEOF_LINETBL_STMT;
+ pc = target_to_host (tblscan, SIZEOF_LINETBL_DELTA, GET_UNSIGNED,
+ current_objfile);
+ tblscan += SIZEOF_LINETBL_DELTA;
+ pc += base;
+ if (line != 0)
+ {
+ record_line (current_subfile, line, pc);
+ }
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ locval -- compute the value of a location attribute
+
+SYNOPSIS
+
+ static int locval (char *loc)
+
+DESCRIPTION
+
+ Given pointer to a string of bytes that define a location, compute
+ the location and return the value.
+
+ When computing values involving the current value of the frame pointer,
+ the value zero is used, which results in a value relative to the frame
+ pointer, rather than the absolute value. This is what GDB wants
+ anyway.
+
+ When the result is a register number, the global isreg flag is set,
+ otherwise it is cleared. This is a kludge until we figure out a better
+ way to handle the problem. Gdb's design does not mesh well with the
+ DWARF notion of a location computing interpreter, which is a shame
+ because the flexibility goes unused.
+
+NOTES
+
+ Note that stack[0] is unused except as a default error return.
+ Note that stack overflow is not yet handled.
+ */
+
+static int
+locval (loc)
+ char *loc;
+{
+ unsigned short nbytes;
+ unsigned short locsize;
+ auto long stack[64];
+ int stacki;
+ char *end;
+ int loc_atom_code;
+ int loc_value_size;
+
+ nbytes = attribute_size (AT_location);
+ locsize = target_to_host (loc, nbytes, GET_UNSIGNED, current_objfile);
+ loc += nbytes;
+ end = loc + locsize;
+ stacki = 0;
+ stack[stacki] = 0;
+ isreg = 0;
+ offreg = 0;
+ loc_value_size = TARGET_FT_LONG_SIZE (current_objfile);
+ while (loc < end)
+ {
+ loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED,
+ current_objfile);
+ loc += SIZEOF_LOC_ATOM_CODE;
+ switch (loc_atom_code)
+ {
+ case 0:
+ /* error */
+ loc = end;
+ break;
+ case OP_REG:
+ /* push register (number) */
+ stack[++stacki] = target_to_host (loc, loc_value_size,
+ GET_UNSIGNED, current_objfile);
+ loc += loc_value_size;
+ isreg = 1;
+ break;
+ case OP_BASEREG:
+ /* push value of register (number) */
+ /* Actually, we compute the value as if register has 0, so the
+ value ends up being the offset from that register. */
+ offreg = 1;
+ basereg = target_to_host (loc, loc_value_size, GET_UNSIGNED,
+ current_objfile);
+ loc += loc_value_size;
+ stack[++stacki] = 0;
+ break;
+ case OP_ADDR:
+ /* push address (relocated address) */
+ stack[++stacki] = target_to_host (loc, loc_value_size,
+ GET_UNSIGNED, current_objfile);
+ loc += loc_value_size;
+ break;
+ case OP_CONST:
+ /* push constant (number) FIXME: signed or unsigned! */
+ stack[++stacki] = target_to_host (loc, loc_value_size,
+ GET_SIGNED, current_objfile);
+ loc += loc_value_size;
+ break;
+ case OP_DEREF2:
+ /* pop, deref and push 2 bytes (as a long) */
+ complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]);
+ break;
+ case OP_DEREF4: /* pop, deref and push 4 bytes (as a long) */
+ complain (&op_deref4, DIE_ID, DIE_NAME, stack[stacki]);
+ break;
+ case OP_ADD: /* pop top 2 items, add, push result */
+ stack[stacki - 1] += stack[stacki];
+ stacki--;
+ break;
+ }
+ }
+ return (stack[stacki]);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_ofile_symtab -- build a full symtab entry from chunk of DIE's
+
+SYNOPSIS
+
+ static void read_ofile_symtab (struct partial_symtab *pst)
+
+DESCRIPTION
+
+ When expanding a partial symbol table entry to a full symbol table
+ entry, this is the function that gets called to read in the symbols
+ for the compilation unit. A pointer to the newly constructed symtab,
+ which is now the new first one on the objfile's symtab list, is
+ stashed in the partial symbol table entry.
+ */
+
+static void
+read_ofile_symtab (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *back_to;
+ unsigned long lnsize;
+ file_ptr foffset;
+ bfd *abfd;
+ char lnsizedata[SIZEOF_LINETBL_LENGTH];
+
+ abfd = pst -> objfile -> obfd;
+ current_objfile = pst -> objfile;
+
+ /* Allocate a buffer for the entire chunk of DIE's for this compilation
+ unit, seek to the location in the file, and read in all the DIE's. */
+
+ diecount = 0;
+ dbsize = DBLENGTH (pst);
+ dbbase = xmalloc (dbsize);
+ dbroff = DBROFF(pst);
+ foffset = DBFOFF(pst) + dbroff;
+ base_section_offsets = pst->section_offsets;
+ baseaddr = ANOFFSET (pst->section_offsets, 0);
+ if (bfd_seek (abfd, foffset, L_SET) ||
+ (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
+ {
+ free (dbbase);
+ error ("can't read DWARF data");
+ }
+ back_to = make_cleanup (free, dbbase);
+
+ /* If there is a line number table associated with this compilation unit
+ then read the size of this fragment in bytes, from the fragment itself.
+ Allocate a buffer for the fragment and read it in for future
+ processing. */
+
+ lnbase = NULL;
+ if (LNFOFF (pst))
+ {
+ if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||
+ (bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) !=
+ sizeof (lnsizedata)))
+ {
+ error ("can't read DWARF line number table size");
+ }
+ lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH,
+ GET_UNSIGNED, pst -> objfile);
+ lnbase = xmalloc (lnsize);
+ if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||
+ (bfd_read (lnbase, lnsize, 1, abfd) != lnsize))
+ {
+ free (lnbase);
+ error ("can't read DWARF line numbers");
+ }
+ make_cleanup (free, lnbase);
+ }
+
+ process_dies (dbbase, dbbase + dbsize, pst -> objfile);
+ do_cleanups (back_to);
+ current_objfile = NULL;
+ pst -> symtab = pst -> objfile -> symtabs;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ psymtab_to_symtab_1 -- do grunt work for building a full symtab entry
+
+SYNOPSIS
+
+ static void psymtab_to_symtab_1 (struct partial_symtab *pst)
+
+DESCRIPTION
+
+ Called once for each partial symbol table entry that needs to be
+ expanded into a full symbol table entry.
+
+*/
+
+static void
+psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ int i;
+ struct cleanup *old_chain;
+
+ if (pst != NULL)
+ {
+ if (pst->readin)
+ {
+ warning ("psymtab for %s already read in. Shouldn't happen.",
+ pst -> filename);
+ }
+ else
+ {
+ /* Read in all partial symtabs 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 ("");
+ fflush (stdout); /* Flush output */
+ }
+ psymtab_to_symtab_1 (pst -> dependencies[i]);
+ }
+ }
+ if (DBLENGTH (pst)) /* Otherwise it's a dummy */
+ {
+ buildsym_init ();
+ old_chain = make_cleanup (really_free_pendings, 0);
+ read_ofile_symtab (pst);
+ if (info_verbose)
+ {
+ printf_filtered ("%d DIE's, sorting...", diecount);
+ wrap_here ("");
+ fflush (stdout);
+ }
+ sort_symtab_syms (pst -> symtab);
+ do_cleanups (old_chain);
+ }
+ pst -> readin = 1;
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ dwarf_psymtab_to_symtab -- build a full symtab entry from partial one
+
+SYNOPSIS
+
+ static void dwarf_psymtab_to_symtab (struct partial_symtab *pst)
+
+DESCRIPTION
+
+ This is the DWARF support entry point for building a full symbol
+ table entry from a partial symbol table entry. We are passed a
+ pointer to the partial symbol table entry that needs to be expanded.
+
+*/
+
+static void
+dwarf_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+
+ if (pst != NULL)
+ {
+ if (pst -> readin)
+ {
+ warning ("psymtab for %s already read in. Shouldn't happen.",
+ pst -> filename);
+ }
+ else
+ {
+ if (DBLENGTH (pst) || pst -> number_of_dependencies)
+ {
+ /* Print the message now, before starting serious work, to avoid
+ disconcerting pauses. */
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...",
+ pst -> filename);
+ fflush (stdout);
+ }
+
+ psymtab_to_symtab_1 (pst);
+
+#if 0 /* FIXME: Check to see what dbxread is doing here and see if
+ we need to do an equivalent or is this something peculiar to
+ stabs/a.out format.
+ 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 (pst -> objfile);
+#endif
+
+ /* Finish up the verbose info message. */
+ if (info_verbose)
+ {
+ printf_filtered ("done.\n");
+ fflush (stdout);
+ }
+ }
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ init_psymbol_list -- initialize storage for partial symbols
+
+SYNOPSIS
+
+ static void init_psymbol_list (struct objfile *objfile, int total_symbols)
+
+DESCRIPTION
+
+ Initializes storage for all of the partial symbols that will be
+ created by dwarf_build_psymtabs and subsidiaries.
+ */
+
+static void
+init_psymbol_list (objfile, total_symbols)
+ struct objfile *objfile;
+ int total_symbols;
+{
+ /* Free any previously allocated psymbol lists. */
+
+ if (objfile -> global_psymbols.list)
+ {
+ mfree (objfile -> md, (PTR)objfile -> global_psymbols.list);
+ }
+ if (objfile -> static_psymbols.list)
+ {
+ mfree (objfile -> md, (PTR)objfile -> 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 */
+
+ objfile -> global_psymbols.size = total_symbols / 10;
+ objfile -> static_psymbols.size = total_symbols / 10;
+ objfile -> global_psymbols.next =
+ objfile -> global_psymbols.list = (struct partial_symbol *)
+ xmmalloc (objfile -> md, objfile -> global_psymbols.size
+ * sizeof (struct partial_symbol));
+ objfile -> static_psymbols.next =
+ objfile -> static_psymbols.list = (struct partial_symbol *)
+ xmmalloc (objfile -> md, objfile -> static_psymbols.size
+ * sizeof (struct partial_symbol));
+}
+
+/*
+
+LOCAL FUNCTION
+
+ add_enum_psymbol -- add enumeration members to partial symbol table
+
+DESCRIPTION
+
+ Given pointer to a DIE that is known to be for an enumeration,
+ extract the symbolic names of the enumeration members and add
+ partial symbols for them.
+*/
+
+static void
+add_enum_psymbol (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ char *scan;
+ char *listend;
+ unsigned short blocksz;
+ int nbytes;
+
+ if ((scan = dip -> at_element_list) != NULL)
+ {
+ if (dip -> short_element_list)
+ {
+ nbytes = attribute_size (AT_short_element_list);
+ }
+ else
+ {
+ nbytes = attribute_size (AT_element_list);
+ }
+ blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile);
+ scan += nbytes;
+ listend = scan + blocksz;
+ while (scan < listend)
+ {
+ scan += TARGET_FT_LONG_SIZE (objfile);
+ ADD_PSYMBOL_TO_LIST (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
+ objfile -> static_psymbols, 0, cu_language,
+ objfile);
+ scan += strlen (scan) + 1;
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ add_partial_symbol -- add symbol to partial symbol table
+
+DESCRIPTION
+
+ Given a DIE, if it is one of the types that we want to
+ add to a partial symbol table, finish filling in the die info
+ and then add a partial symbol table entry for it.
+
+NOTES
+
+ The caller must ensure that the DIE has a valid name attribute.
+*/
+
+static void
+add_partial_symbol (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ switch (dip -> die_tag)
+ {
+ case TAG_global_subroutine:
+ ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ objfile -> global_psymbols,
+ dip -> at_low_pc, cu_language, objfile);
+ break;
+ case TAG_global_variable:
+ ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_STATIC,
+ objfile -> global_psymbols,
+ 0, cu_language, objfile);
+ break;
+ case TAG_subroutine:
+ ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ objfile -> static_psymbols,
+ dip -> at_low_pc, cu_language, objfile);
+ break;
+ case TAG_local_variable:
+ ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_STATIC,
+ objfile -> static_psymbols,
+ 0, cu_language, objfile);
+ break;
+ case TAG_typedef:
+ ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ objfile -> static_psymbols,
+ 0, cu_language, objfile);
+ break;
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ case TAG_enumeration_type:
+ ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ objfile -> static_psymbols,
+ 0, cu_language, objfile);
+ if (cu_language == language_cplus)
+ {
+ /* For C++, these implicitly act as typedefs as well. */
+ ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ objfile -> static_psymbols,
+ 0, cu_language, objfile);
+ }
+ break;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ scan_partial_symbols -- scan DIE's within a single compilation unit
+
+DESCRIPTION
+
+ Process the DIE's within a single compilation unit, looking for
+ interesting DIE's that contribute to the partial symbol table entry
+ for this compilation unit.
+
+NOTES
+
+ There are some DIE's that may appear both at file scope and within
+ the scope of a function. We are only interested in the ones at file
+ scope, and the only way to tell them apart is to keep track of the
+ scope. For example, consider the test case:
+
+ static int i;
+ main () { int j; }
+
+ for which the relevant DWARF segment has the structure:
+
+ 0x51:
+ 0x23 global subrtn sibling 0x9b
+ name main
+ fund_type FT_integer
+ low_pc 0x800004cc
+ high_pc 0x800004d4
+
+ 0x74:
+ 0x23 local var sibling 0x97
+ name j
+ fund_type FT_integer
+ location OP_BASEREG 0xe
+ OP_CONST 0xfffffffc
+ OP_ADD
+ 0x97:
+ 0x4
+
+ 0x9b:
+ 0x1d local var sibling 0xb8
+ name i
+ fund_type FT_integer
+ location OP_ADDR 0x800025dc
+
+ 0xb8:
+ 0x4
+
+ We want to include the symbol 'i' in the partial symbol table, but
+ not the symbol 'j'. In essence, we want to skip all the dies within
+ the scope of a TAG_global_subroutine DIE.
+
+ Don't attempt to add anonymous structures or unions since they have
+ no name. Anonymous enumerations however are processed, because we
+ want to extract their member names (the check for a tag name is
+ done later).
+
+ Also, for variables and subroutines, check that this is the place
+ where the actual definition occurs, rather than just a reference
+ to an external.
+ */
+
+static void
+scan_partial_symbols (thisdie, enddie, objfile)
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ char *nextdie;
+ char *temp;
+ struct dieinfo di;
+
+ while (thisdie < enddie)
+ {
+ basicdieinfo (&di, thisdie, objfile);
+ if (di.die_length < SIZEOF_DIE_LENGTH)
+ {
+ break;
+ }
+ else
+ {
+ nextdie = thisdie + di.die_length;
+ /* To avoid getting complete die information for every die, we
+ only do it (below) for the cases we are interested in. */
+ switch (di.die_tag)
+ {
+ case TAG_global_subroutine:
+ case TAG_subroutine:
+ completedieinfo (&di, objfile);
+ if (di.at_name && (di.has_at_low_pc || di.at_location))
+ {
+ add_partial_symbol (&di, objfile);
+ /* If there is a sibling attribute, adjust the nextdie
+ pointer to skip the entire scope of the subroutine.
+ Apply some sanity checking to make sure we don't
+ overrun or underrun the range of remaining DIE's */
+ if (di.at_sibling != 0)
+ {
+ temp = dbbase + di.at_sibling - dbroff;
+ if ((temp < thisdie) || (temp >= enddie))
+ {
+ complain (&bad_die_ref, DIE_ID, DIE_NAME,
+ di.at_sibling);
+ }
+ else
+ {
+ nextdie = temp;
+ }
+ }
+ }
+ break;
+ case TAG_global_variable:
+ case TAG_local_variable:
+ completedieinfo (&di, objfile);
+ if (di.at_name && (di.has_at_low_pc || di.at_location))
+ {
+ add_partial_symbol (&di, objfile);
+ }
+ break;
+ case TAG_typedef:
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ completedieinfo (&di, objfile);
+ if (di.at_name)
+ {
+ add_partial_symbol (&di, objfile);
+ }
+ break;
+ case TAG_enumeration_type:
+ completedieinfo (&di, objfile);
+ if (di.at_name)
+ {
+ add_partial_symbol (&di, objfile);
+ }
+ add_enum_psymbol (&di, objfile);
+ break;
+ }
+ }
+ thisdie = nextdie;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ scan_compilation_units -- build a psymtab entry for each compilation
+
+DESCRIPTION
+
+ This is the top level dwarf parsing routine for building partial
+ symbol tables.
+
+ It scans from the beginning of the DWARF table looking for the first
+ TAG_compile_unit DIE, and then follows the sibling chain to locate
+ each additional TAG_compile_unit DIE.
+
+ For each TAG_compile_unit DIE it creates a partial symtab structure,
+ calls a subordinate routine to collect all the compilation unit's
+ global DIE's, file scope DIEs, typedef DIEs, etc, and then links the
+ new partial symtab structure into the partial symbol table. It also
+ records the appropriate information in the partial symbol table entry
+ to allow the chunk of DIE's and line number table for this compilation
+ unit to be located and re-read later, to generate a complete symbol
+ table entry for the compilation unit.
+
+ Thus it effectively partitions up a chunk of DIE's for multiple
+ compilation units into smaller DIE chunks and line number tables,
+ and associates them with a partial symbol table entry.
+
+NOTES
+
+ If any compilation unit has no line number table associated with
+ it for some reason (a missing at_stmt_list attribute, rather than
+ just one with a value of zero, which is valid) then we ensure that
+ the recorded file offset is zero so that the routine which later
+ reads line number table fragments knows that there is no fragment
+ to read.
+
+RETURNS
+
+ Returns no value.
+
+ */
+
+static void
+scan_compilation_units (thisdie, enddie, dbfoff, lnoffset, objfile)
+ char *thisdie;
+ char *enddie;
+ file_ptr dbfoff;
+ file_ptr lnoffset;
+ struct objfile *objfile;
+{
+ char *nextdie;
+ struct dieinfo di;
+ struct partial_symtab *pst;
+ int culength;
+ int curoff;
+ file_ptr curlnoffset;
+
+ while (thisdie < enddie)
+ {
+ basicdieinfo (&di, thisdie, objfile);
+ if (di.die_length < SIZEOF_DIE_LENGTH)
+ {
+ break;
+ }
+ else if (di.die_tag != TAG_compile_unit)
+ {
+ nextdie = thisdie + di.die_length;
+ }
+ else
+ {
+ completedieinfo (&di, objfile);
+ set_cu_language (&di);
+ if (di.at_sibling != 0)
+ {
+ nextdie = dbbase + di.at_sibling - dbroff;
+ }
+ else
+ {
+ nextdie = thisdie + di.die_length;
+ }
+ curoff = thisdie - dbbase;
+ culength = nextdie - thisdie;
+ curlnoffset = di.has_at_stmt_list ? lnoffset + di.at_stmt_list : 0;
+
+ /* First allocate a new partial symbol table structure */
+
+ pst = start_psymtab_common (objfile, base_section_offsets,
+ di.at_name, di.at_low_pc,
+ objfile -> global_psymbols.next,
+ objfile -> static_psymbols.next);
+
+ pst -> texthigh = di.at_high_pc;
+ pst -> read_symtab_private = (char *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct dwfinfo));
+ DBFOFF (pst) = dbfoff;
+ DBROFF (pst) = curoff;
+ DBLENGTH (pst) = culength;
+ LNFOFF (pst) = curlnoffset;
+ pst -> read_symtab = dwarf_psymtab_to_symtab;
+
+ /* Now look for partial symbols */
+
+ scan_partial_symbols (thisdie + di.die_length, nextdie, objfile);
+
+ pst -> n_global_syms = objfile -> global_psymbols.next -
+ (objfile -> global_psymbols.list + pst -> globals_offset);
+ pst -> n_static_syms = objfile -> static_psymbols.next -
+ (objfile -> static_psymbols.list + pst -> statics_offset);
+ sort_pst_symbols (pst);
+ /* If there is already a psymtab or symtab for a file of this name,
+ remove it. (If there is a symtab, more drastic things also
+ happen.) This happens in VxWorks. */
+ free_named_symtabs (pst -> filename);
+ }
+ thisdie = nextdie;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ new_symbol -- make a symbol table entry for a new symbol
+
+SYNOPSIS
+
+ static struct symbol *new_symbol (struct dieinfo *dip,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to a DWARF information entry, figure out if we need
+ to make a symbol table entry for it, and if so, create a new entry
+ and return a pointer to it.
+ */
+
+static struct symbol *
+new_symbol (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ struct symbol *sym = NULL;
+
+ if (dip -> at_name != NULL)
+ {
+ sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = create_name (dip -> at_name,
+ &objfile->symbol_obstack);
+ /* default assumptions */
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_TYPE (sym) = decode_die_type (dip);
+
+ /* If this symbol is from a C++ compilation, then attempt to cache the
+ demangled form for future reference. This is a typical time versus
+ space tradeoff, that was decided in favor of time because it sped up
+ C++ symbol lookups by a factor of about 20. */
+
+ SYMBOL_LANGUAGE (sym) = cu_language;
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile -> symbol_obstack);
+ switch (dip -> die_tag)
+ {
+ case TAG_label:
+ SYMBOL_VALUE (sym) = dip -> at_low_pc;
+ SYMBOL_CLASS (sym) = LOC_LABEL;
+ break;
+ case TAG_global_subroutine:
+ case TAG_subroutine:
+ SYMBOL_VALUE (sym) = dip -> at_low_pc;
+ SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ if (dip -> die_tag == TAG_global_subroutine)
+ {
+ add_symbol_to_list (sym, &global_symbols);
+ }
+ else
+ {
+ add_symbol_to_list (sym, list_in_scope);
+ }
+ break;
+ case TAG_global_variable:
+ if (dip -> at_location != NULL)
+ {
+ SYMBOL_VALUE (sym) = locval (dip -> at_location);
+ add_symbol_to_list (sym, &global_symbols);
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE (sym) += baseaddr;
+ }
+ break;
+ case TAG_local_variable:
+ if (dip -> at_location != NULL)
+ {
+ SYMBOL_VALUE (sym) = locval (dip -> at_location);
+ add_symbol_to_list (sym, list_in_scope);
+ if (isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ }
+ else if (offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG;
+ SYMBOL_BASEREG (sym) = basereg;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE (sym) += baseaddr;
+ }
+ }
+ break;
+ case TAG_formal_parameter:
+ if (dip -> at_location != NULL)
+ {
+ SYMBOL_VALUE (sym) = locval (dip -> at_location);
+ }
+ add_symbol_to_list (sym, list_in_scope);
+ if (isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ }
+ else if (offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+ SYMBOL_BASEREG (sym) = basereg;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ }
+ break;
+ case TAG_unspecified_parameters:
+ /* From varargs functions; gdb doesn't seem to have any interest in
+ this information, so just ignore it for now. (FIXME?) */
+ break;
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ case TAG_enumeration_type:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+ break;
+ case TAG_typedef:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+ break;
+ default:
+ /* Not a tag we recognize. Hopefully we aren't processing trash
+ data, but since we must specifically ignore things we don't
+ recognize, there is nothing else we should do at this point. */
+ break;
+ }
+ }
+ return (sym);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ synthesize_typedef -- make a symbol table entry for a "fake" typedef
+
+SYNOPSIS
+
+ static void synthesize_typedef (struct dieinfo *dip,
+ struct objfile *objfile,
+ struct type *type);
+
+DESCRIPTION
+
+ Given a pointer to a DWARF information entry, synthesize a typedef
+ for the name in the DIE, using the specified type.
+
+ This is used for C++ class, structs, unions, and enumerations to
+ set up the tag name as a type.
+
+ */
+
+static void
+synthesize_typedef (dip, objfile, type)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+ struct type *type;
+{
+ struct symbol *sym = NULL;
+
+ if (dip -> at_name != NULL)
+ {
+ sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = create_name (dip -> at_name,
+ &objfile->symbol_obstack);
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_mod_fund_type -- decode a modified fundamental type
+
+SYNOPSIS
+
+ static struct type *decode_mod_fund_type (char *typedata)
+
+DESCRIPTION
+
+ Decode a block of data containing a modified fundamental
+ type specification. TYPEDATA is a pointer to the block,
+ which starts with a length containing the size of the rest
+ of the block. At the end of the block is a fundmental type
+ code value that gives the fundamental type. Everything
+ in between are type modifiers.
+
+ We simply compute the number of modifiers and call the general
+ function decode_modified_type to do the actual work.
+*/
+
+static struct type *
+decode_mod_fund_type (typedata)
+ char *typedata;
+{
+ struct type *typep = NULL;
+ unsigned short modcount;
+ int nbytes;
+
+ /* Get the total size of the block, exclusive of the size itself */
+
+ nbytes = attribute_size (AT_mod_fund_type);
+ modcount = target_to_host (typedata, nbytes, GET_UNSIGNED, current_objfile);
+ typedata += nbytes;
+
+ /* Deduct the size of the fundamental type bytes at the end of the block. */
+
+ modcount -= attribute_size (AT_fund_type);
+
+ /* Now do the actual decoding */
+
+ typep = decode_modified_type (typedata, modcount, AT_mod_fund_type);
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_mod_u_d_type -- decode a modified user defined type
+
+SYNOPSIS
+
+ static struct type *decode_mod_u_d_type (char *typedata)
+
+DESCRIPTION
+
+ Decode a block of data containing a modified user defined
+ type specification. TYPEDATA is a pointer to the block,
+ which consists of a two byte length, containing the size
+ of the rest of the block. At the end of the block is a
+ four byte value that gives a reference to a user defined type.
+ Everything in between are type modifiers.
+
+ We simply compute the number of modifiers and call the general
+ function decode_modified_type to do the actual work.
+*/
+
+static struct type *
+decode_mod_u_d_type (typedata)
+ char *typedata;
+{
+ struct type *typep = NULL;
+ unsigned short modcount;
+ int nbytes;
+
+ /* Get the total size of the block, exclusive of the size itself */
+
+ nbytes = attribute_size (AT_mod_u_d_type);
+ modcount = target_to_host (typedata, nbytes, GET_UNSIGNED, current_objfile);
+ typedata += nbytes;
+
+ /* Deduct the size of the reference type bytes at the end of the block. */
+
+ modcount -= attribute_size (AT_user_def_type);
+
+ /* Now do the actual decoding */
+
+ typep = decode_modified_type (typedata, modcount, AT_mod_u_d_type);
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_modified_type -- decode modified user or fundamental type
+
+SYNOPSIS
+
+ static struct type *decode_modified_type (char *modifiers,
+ unsigned short modcount, int mtype)
+
+DESCRIPTION
+
+ Decode a modified type, either a modified fundamental type or
+ a modified user defined type. MODIFIERS is a pointer to the
+ block of bytes that define MODCOUNT modifiers. Immediately
+ following the last modifier is a short containing the fundamental
+ type or a long containing the reference to the user defined
+ type. Which one is determined by MTYPE, which is either
+ AT_mod_fund_type or AT_mod_u_d_type to indicate what modified
+ type we are generating.
+
+ We call ourself recursively to generate each modified type,`
+ until MODCOUNT reaches zero, at which point we have consumed
+ all the modifiers and generate either the fundamental type or
+ user defined type. When the recursion unwinds, each modifier
+ is applied in turn to generate the full modified type.
+
+NOTES
+
+ If we find a modifier that we don't recognize, and it is not one
+ of those reserved for application specific use, then we issue a
+ warning and simply ignore the modifier.
+
+BUGS
+
+ We currently ignore MOD_const and MOD_volatile. (FIXME)
+
+ */
+
+static struct type *
+decode_modified_type (modifiers, modcount, mtype)
+ char *modifiers;
+ unsigned int modcount;
+ int mtype;
+{
+ struct type *typep = NULL;
+ unsigned short fundtype;
+ DIE_REF die_ref;
+ char modifier;
+ int nbytes;
+
+ if (modcount == 0)
+ {
+ switch (mtype)
+ {
+ case AT_mod_fund_type:
+ nbytes = attribute_size (AT_fund_type);
+ fundtype = target_to_host (modifiers, nbytes, GET_UNSIGNED,
+ current_objfile);
+ typep = decode_fund_type (fundtype);
+ break;
+ case AT_mod_u_d_type:
+ nbytes = attribute_size (AT_user_def_type);
+ die_ref = target_to_host (modifiers, nbytes, GET_UNSIGNED,
+ current_objfile);
+ if ((typep = lookup_utype (die_ref)) == NULL)
+ {
+ typep = alloc_utype (die_ref, NULL);
+ }
+ break;
+ default:
+ complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype);
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ break;
+ }
+ }
+ else
+ {
+ modifier = *modifiers++;
+ typep = decode_modified_type (modifiers, --modcount, mtype);
+ switch (modifier)
+ {
+ case MOD_pointer_to:
+ typep = lookup_pointer_type (typep);
+ break;
+ case MOD_reference_to:
+ typep = lookup_reference_type (typep);
+ break;
+ case MOD_const:
+ complain (&const_ignored, DIE_ID, DIE_NAME); /* FIXME */
+ break;
+ case MOD_volatile:
+ complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */
+ break;
+ default:
+ if (!(MOD_lo_user <= (unsigned char) modifier
+ && (unsigned char) modifier <= MOD_hi_user))
+ {
+ complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier);
+ }
+ break;
+ }
+ }
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_fund_type -- translate basic DWARF type to gdb base type
+
+DESCRIPTION
+
+ Given an integer that is one of the fundamental DWARF types,
+ translate it to one of the basic internal gdb types and return
+ a pointer to the appropriate gdb type (a "struct type *").
+
+NOTES
+
+ For robustness, if we are asked to translate a fundamental
+ type that we are unprepared to deal with, we return int so
+ callers can always depend upon a valid type being returned,
+ and so gdb may at least do something reasonable by default.
+ If the type is not in the range of those types defined as
+ application specific types, we also issue a warning.
+*/
+
+static struct type *
+decode_fund_type (fundtype)
+ unsigned int fundtype;
+{
+ struct type *typep = NULL;
+
+ switch (fundtype)
+ {
+
+ case FT_void:
+ typep = dwarf_fundamental_type (current_objfile, FT_VOID);
+ break;
+
+ case FT_boolean: /* Was FT_set in AT&T version */
+ typep = dwarf_fundamental_type (current_objfile, FT_BOOLEAN);
+ break;
+
+ case FT_pointer: /* (void *) */
+ typep = dwarf_fundamental_type (current_objfile, FT_VOID);
+ typep = lookup_pointer_type (typep);
+ break;
+
+ case FT_char:
+ typep = dwarf_fundamental_type (current_objfile, FT_CHAR);
+ break;
+
+ case FT_signed_char:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+ break;
+
+ case FT_unsigned_char:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+ break;
+
+ case FT_short:
+ typep = dwarf_fundamental_type (current_objfile, FT_SHORT);
+ break;
+
+ case FT_signed_short:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_SHORT);
+ break;
+
+ case FT_unsigned_short:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
+ break;
+
+ case FT_integer:
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ break;
+
+ case FT_signed_integer:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
+ break;
+
+ case FT_unsigned_integer:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+ break;
+
+ case FT_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_LONG);
+ break;
+
+ case FT_signed_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG);
+ break;
+
+ case FT_unsigned_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
+ break;
+
+ case FT_long_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_LONG_LONG);
+ break;
+
+ case FT_signed_long_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG);
+ break;
+
+ case FT_unsigned_long_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG);
+ break;
+
+ case FT_float:
+ typep = dwarf_fundamental_type (current_objfile, FT_FLOAT);
+ break;
+
+ case FT_dbl_prec_float:
+ typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+ break;
+
+ case FT_ext_prec_float:
+ typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
+ break;
+
+ case FT_complex:
+ typep = dwarf_fundamental_type (current_objfile, FT_COMPLEX);
+ break;
+
+ case FT_dbl_prec_complex:
+ typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX);
+ break;
+
+ case FT_ext_prec_complex:
+ typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX);
+ break;
+
+ }
+
+ if (typep == NULL)
+ {
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ if (!(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
+ {
+ complain (&unexpected_fund_type, DIE_ID, DIE_NAME, fundtype);
+ }
+ }
+
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ create_name -- allocate a fresh copy of a string on an obstack
+
+DESCRIPTION
+
+ Given a pointer to a string and a pointer to an obstack, allocates
+ a fresh copy of the string on the specified obstack.
+
+*/
+
+static char *
+create_name (name, obstackp)
+ char *name;
+ struct obstack *obstackp;
+{
+ int length;
+ char *newname;
+
+ length = strlen (name) + 1;
+ newname = (char *) obstack_alloc (obstackp, length);
+ strcpy (newname, name);
+ return (newname);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ basicdieinfo -- extract the minimal die info from raw die data
+
+SYNOPSIS
+
+ void basicdieinfo (char *diep, struct dieinfo *dip,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to raw DIE data, and a pointer to an instance of a
+ die info structure, this function extracts the basic information
+ from the DIE data required to continue processing this DIE, along
+ with some bookkeeping information about the DIE.
+
+ The information we absolutely must have includes the DIE tag,
+ and the DIE length. If we need the sibling reference, then we
+ will have to call completedieinfo() to process all the remaining
+ DIE information.
+
+ Note that since there is no guarantee that the data is properly
+ aligned in memory for the type of access required (indirection
+ through anything other than a char pointer), and there is no
+ guarantee that it is in the same byte order as the gdb host,
+ we call a function which deals with both alignment and byte
+ swapping issues. Possibly inefficient, but quite portable.
+
+ We also take care of some other basic things at this point, such
+ as ensuring that the instance of the die info structure starts
+ out completely zero'd and that curdie is initialized for use
+ in error reporting if we have a problem with the current die.
+
+NOTES
+
+ All DIE's must have at least a valid length, thus the minimum
+ DIE size is SIZEOF_DIE_LENGTH. In order to have a valid tag, the
+ DIE size must be at least SIZEOF_DIE_TAG larger, otherwise they
+ are forced to be TAG_padding DIES.
+
+ Padding DIES must be at least SIZEOF_DIE_LENGTH in length, implying
+ that if a padding DIE is used for alignment and the amount needed is
+ less than SIZEOF_DIE_LENGTH, then the padding DIE has to be big
+ enough to align to the next alignment boundry.
+
+ We do some basic sanity checking here, such as verifying that the
+ length of the die would not cause it to overrun the recorded end of
+ the buffer holding the DIE info. If we find a DIE that is either
+ too small or too large, we force it's length to zero which should
+ cause the caller to take appropriate action.
+ */
+
+static void
+basicdieinfo (dip, diep, objfile)
+ struct dieinfo *dip;
+ char *diep;
+ struct objfile *objfile;
+{
+ curdie = dip;
+ memset (dip, 0, sizeof (struct dieinfo));
+ dip -> die = diep;
+ dip -> die_ref = dbroff + (diep - dbbase);
+ dip -> die_length = target_to_host (diep, SIZEOF_DIE_LENGTH, GET_UNSIGNED,
+ objfile);
+ if ((dip -> die_length < SIZEOF_DIE_LENGTH) ||
+ ((diep + dip -> die_length) > (dbbase + dbsize)))
+ {
+ complain (&malformed_die, DIE_ID, DIE_NAME, dip -> die_length);
+ dip -> die_length = 0;
+ }
+ else if (dip -> die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG))
+ {
+ dip -> die_tag = TAG_padding;
+ }
+ else
+ {
+ diep += SIZEOF_DIE_LENGTH;
+ dip -> die_tag = target_to_host (diep, SIZEOF_DIE_TAG, GET_UNSIGNED,
+ objfile);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ completedieinfo -- finish reading the information for a given DIE
+
+SYNOPSIS
+
+ void completedieinfo (struct dieinfo *dip, struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to an already partially initialized die info structure,
+ scan the raw DIE data and finish filling in the die info structure
+ from the various attributes found.
+
+ Note that since there is no guarantee that the data is properly
+ aligned in memory for the type of access required (indirection
+ through anything other than a char pointer), and there is no
+ guarantee that it is in the same byte order as the gdb host,
+ we call a function which deals with both alignment and byte
+ swapping issues. Possibly inefficient, but quite portable.
+
+NOTES
+
+ Each time we are called, we increment the diecount variable, which
+ keeps an approximate count of the number of dies processed for
+ each compilation unit. This information is presented to the user
+ if the info_verbose flag is set.
+
+ */
+
+static void
+completedieinfo (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ char *diep; /* Current pointer into raw DIE data */
+ char *end; /* Terminate DIE scan here */
+ unsigned short attr; /* Current attribute being scanned */
+ unsigned short form; /* Form of the attribute */
+ int nbytes; /* Size of next field to read */
+
+ diecount++;
+ diep = dip -> die;
+ end = diep + dip -> die_length;
+ diep += SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG;
+ while (diep < end)
+ {
+ attr = target_to_host (diep, SIZEOF_ATTRIBUTE, GET_UNSIGNED, objfile);
+ diep += SIZEOF_ATTRIBUTE;
+ if ((nbytes = attribute_size (attr)) == -1)
+ {
+ complain (&unknown_attribute_length, DIE_ID, DIE_NAME);
+ diep = end;
+ continue;
+ }
+ switch (attr)
+ {
+ case AT_fund_type:
+ dip -> at_fund_type = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_ordering:
+ dip -> at_ordering = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_bit_offset:
+ dip -> at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_sibling:
+ dip -> at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_stmt_list:
+ dip -> at_stmt_list = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ dip -> has_at_stmt_list = 1;
+ break;
+ case AT_low_pc:
+ dip -> at_low_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ dip -> at_low_pc += baseaddr;
+ dip -> has_at_low_pc = 1;
+ break;
+ case AT_high_pc:
+ dip -> at_high_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ dip -> at_high_pc += baseaddr;
+ break;
+ case AT_language:
+ dip -> at_language = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_user_def_type:
+ dip -> at_user_def_type = target_to_host (diep, nbytes,
+ GET_UNSIGNED, objfile);
+ break;
+ case AT_byte_size:
+ dip -> at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ dip -> has_at_byte_size = 1;
+ break;
+ case AT_bit_size:
+ dip -> at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_member:
+ dip -> at_member = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_discr:
+ dip -> at_discr = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_location:
+ dip -> at_location = diep;
+ break;
+ case AT_mod_fund_type:
+ dip -> at_mod_fund_type = diep;
+ break;
+ case AT_subscr_data:
+ dip -> at_subscr_data = diep;
+ break;
+ case AT_mod_u_d_type:
+ dip -> at_mod_u_d_type = diep;
+ break;
+ case AT_element_list:
+ dip -> at_element_list = diep;
+ dip -> short_element_list = 0;
+ break;
+ case AT_short_element_list:
+ dip -> at_element_list = diep;
+ dip -> short_element_list = 1;
+ break;
+ case AT_discr_value:
+ dip -> at_discr_value = diep;
+ break;
+ case AT_string_length:
+ dip -> at_string_length = diep;
+ break;
+ case AT_name:
+ dip -> at_name = diep;
+ break;
+ case AT_comp_dir:
+ /* For now, ignore any "hostname:" portion, since gdb doesn't
+ know how to deal with it. (FIXME). */
+ dip -> at_comp_dir = strrchr (diep, ':');
+ if (dip -> at_comp_dir != NULL)
+ {
+ dip -> at_comp_dir++;
+ }
+ else
+ {
+ dip -> at_comp_dir = diep;
+ }
+ break;
+ case AT_producer:
+ dip -> at_producer = diep;
+ break;
+ case AT_start_scope:
+ dip -> at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_stride_size:
+ dip -> at_stride_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_src_info:
+ dip -> at_src_info = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_prototyped:
+ dip -> at_prototyped = diep;
+ break;
+ default:
+ /* Found an attribute that we are unprepared to handle. However
+ it is specifically one of the design goals of DWARF that
+ consumers should ignore unknown attributes. As long as the
+ form is one that we recognize (so we know how to skip it),
+ we can just ignore the unknown attribute. */
+ break;
+ }
+ form = FORM_FROM_ATTR (attr);
+ switch (form)
+ {
+ case FORM_DATA2:
+ diep += 2;
+ break;
+ case FORM_DATA4:
+ case FORM_REF:
+ diep += 4;
+ break;
+ case FORM_DATA8:
+ diep += 8;
+ break;
+ case FORM_ADDR:
+ diep += TARGET_FT_POINTER_SIZE (objfile);
+ break;
+ case FORM_BLOCK2:
+ diep += 2 + target_to_host (diep, nbytes, GET_UNSIGNED, objfile);
+ break;
+ case FORM_BLOCK4:
+ diep += 4 + target_to_host (diep, nbytes, GET_UNSIGNED, objfile);
+ break;
+ case FORM_STRING:
+ diep += strlen (diep) + 1;
+ break;
+ default:
+ complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
+ diep = end;
+ break;
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ target_to_host -- swap in target data to host
+
+SYNOPSIS
+
+ target_to_host (char *from, int nbytes, int signextend,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given pointer to data in target format in FROM, a byte count for
+ the size of the data in NBYTES, a flag indicating whether or not
+ the data is signed in SIGNEXTEND, and a pointer to the current
+ objfile in OBJFILE, convert the data to host format and return
+ the converted value.
+
+NOTES
+
+ FIXME: If we read data that is known to be signed, and expect to
+ use it as signed data, then we need to explicitly sign extend the
+ result until the bfd library is able to do this for us.
+
+ */
+
+static unsigned long
+target_to_host (from, nbytes, signextend, objfile)
+ char *from;
+ int nbytes;
+ int signextend; /* FIXME: Unused */
+ struct objfile *objfile;
+{
+ unsigned long rtnval;
+
+ switch (nbytes)
+ {
+ case 8:
+ rtnval = bfd_get_64 (objfile -> obfd, (bfd_byte *) from);
+ break;
+ case 4:
+ rtnval = bfd_get_32 (objfile -> obfd, (bfd_byte *) from);
+ break;
+ case 2:
+ rtnval = bfd_get_16 (objfile -> obfd, (bfd_byte *) from);
+ break;
+ case 1:
+ rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from);
+ break;
+ default:
+ complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes);
+ rtnval = 0;
+ break;
+ }
+ return (rtnval);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ attribute_size -- compute size of data for a DWARF attribute
+
+SYNOPSIS
+
+ static int attribute_size (unsigned int attr)
+
+DESCRIPTION
+
+ Given a DWARF attribute in ATTR, compute the size of the first
+ piece of data associated with this attribute and return that
+ size.
+
+ Returns -1 for unrecognized attributes.
+
+ */
+
+static int
+attribute_size (attr)
+ unsigned int attr;
+{
+ int nbytes; /* Size of next data for this attribute */
+ unsigned short form; /* Form of the attribute */
+
+ form = FORM_FROM_ATTR (attr);
+ switch (form)
+ {
+ case FORM_STRING: /* A variable length field is next */
+ nbytes = 0;
+ break;
+ case FORM_DATA2: /* Next 2 byte field is the data itself */
+ case FORM_BLOCK2: /* Next 2 byte field is a block length */
+ nbytes = 2;
+ break;
+ case FORM_DATA4: /* Next 4 byte field is the data itself */
+ case FORM_BLOCK4: /* Next 4 byte field is a block length */
+ case FORM_REF: /* Next 4 byte field is a DIE offset */
+ nbytes = 4;
+ break;
+ case FORM_DATA8: /* Next 8 byte field is the data itself */
+ nbytes = 8;
+ break;
+ case FORM_ADDR: /* Next field size is target sizeof(void *) */
+ nbytes = TARGET_FT_POINTER_SIZE (objfile);
+ break;
+ default:
+ complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
+ nbytes = -1;
+ break;
+ }
+ return (nbytes);
+}
diff --git a/gnu/usr.bin/gdb/gdb/elf/common.h b/gnu/usr.bin/gdb/gdb/elf/common.h
new file mode 100644
index 000000000000..cd708f1489cf
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/elf/common.h
@@ -0,0 +1,216 @@
+/* ELF support for BFD.
+ Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ Cygnus Support, from information published
+ in "UNIX System V Release 4, Programmers Guide: ANSI C and
+ Programming Support Tools".
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This file is part of ELF support for BFD, and contains the portions
+ that are common to both the internal and external representations.
+ For example, ELFMAG0 is the byte 0x7F in both the internal (in-memory)
+ and external (in-file) representations. */
+
+
+/* Fields in e_ident[] */
+
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define ELFMAG0 0x7F /* Magic number byte 0 */
+
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+#define EI_CLASS 4 /* File class */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+
+#define EI_DATA 5 /* Data encoding */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
+
+#define EI_VERSION 6 /* File version */
+
+#define EI_PAD 7 /* Start of padding bytes */
+
+
+/* Values for e_type, which identifies the object file type */
+
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_LOPROC 0xFF00 /* Processor-specific */
+#define ET_HIPROC 0xFFFF /* Processor-specific */
+
+/* Values for e_machine, which identifies the architecture */
+
+#define EM_NONE 0 /* No machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SUN SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola m68k family */
+#define EM_88K 5 /* Motorola m88k family */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 */
+#define EM_HPPA 9 /* HP PA-RISC */
+
+
+/* Values for e_version */
+
+#define EV_NONE 0 /* Invalid ELF version */
+#define EV_CURRENT 1 /* Current version */
+
+/* Values for program header, p_type field */
+
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved, unspecified semantics */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_LOPROC 0x70000000 /* Processor-specific */
+#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
+
+/* Program segment permissions, in program header p_flags field */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+#define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
+
+/* Values for section header, sh_type field */
+
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program specific (private) data */
+#define SHT_SYMTAB 2 /* Link editing symbol table */
+#define SHT_STRTAB 3 /* A string table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* A symbol hash table */
+#define SHT_DYNAMIC 6 /* Information for dynamic linking */
+#define SHT_NOTE 7 /* Information that marks file */
+#define SHT_NOBITS 8 /* Section occupies no space in file */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved, unspecified semantics */
+#define SHT_DYNSYM 11 /* Dynamic linking symbol table */
+#define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */
+#define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */
+#define SHT_LOUSER 0x80000000 /* Application-specific semantics */
+#define SHT_HIUSER 0x8FFFFFFF /* Application-specific semantics */
+
+/* Values for section header, sh_flags field */
+
+#define SHF_WRITE (1 << 0) /* Writable data during execution */
+#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */
+#define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */
+
+/* Values of note segment descriptor types for core files. */
+
+#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
+#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
+#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
+
+/* Values of note segment descriptor types for object files. */
+/* (Only for hppa right now. Should this be moved elsewhere?) */
+
+#define NT_VERSION 1 /* Contains a version string. */
+
+/* These three macros disassemble and assemble a symbol table st_info field,
+ which contains the symbol binding and symbol type. The STB_ and STT_
+ defines identify the binding and type. */
+
+#define ELF_ST_BIND(val) (((unsigned int)(val)) >> 4)
+#define ELF_ST_TYPE(val) ((val) & 0xF)
+#define ELF_ST_INFO(bind,type) (((bind) << 4) + ((type) & 0xF))
+
+#define STN_UNDEF 0 /* undefined symbol index */
+
+#define STB_LOCAL 0 /* Symbol not visible outside obj */
+#define STB_GLOBAL 1 /* Symbol visible outside obj */
+#define STB_WEAK 2 /* Like globals, lower precedence */
+#define STB_LOPROC 13 /* Application-specific semantics */
+#define STB_HIPROC 15 /* Application-specific semantics */
+
+#define STT_NOTYPE 0 /* Symbol type is unspecified */
+#define STT_OBJECT 1 /* Symbol is a data object */
+#define STT_FUNC 2 /* Symbol is a code object */
+#define STT_SECTION 3 /* Symbol associated with a section */
+#define STT_FILE 4 /* Symbol gives a file name */
+#define STT_LOPROC 13 /* Application-specific semantics */
+#define STT_HIPROC 15 /* Application-specific semantics */
+
+/* Special section indices, which may show up in st_shndx fields, among
+ other places. */
+
+#define SHN_UNDEF 0 /* Undefined section reference */
+#define SHN_LORESERV 0xFF00 /* Begin range of reserved indices */
+#define SHN_LOPROC 0xFF00 /* Begin range of appl-specific */
+#define SHN_HIPROC 0xFF1F /* End range of appl-specific */
+#define SHN_ABS 0xFFF1 /* Associated symbol is absolute */
+#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
+#define SHN_HIRESERVE 0xFFFF /* End range of reserved indices */
+
+/* relocation info handling macros */
+
+#define ELF32_R_SYM(i) ((i)>>8)
+#define ELF32_R_TYPE(i) ((unsigned char)(i))
+#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t))
+
+#define ELF64_R_SYM(i) ((i)>>32)
+#define ELF64_R_TYPE(i) ((Elf64_Word)(i))
+#define ELF64_R_INFO(s,t) (((Elf64_Xword)(s)<<32)+(Elf64_Xword)(t))
+
+/* Dynamic section tags */
+
+#define DT_NULL 0
+#define DT_NEEDED 1
+#define DT_PLTRELSZ 2
+#define DT_PLTGOT 3
+#define DT_HASH 4
+#define DT_STRTAB 5
+#define DT_SYMTAB 6
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_STRSZ 10
+#define DT_SYMENT 11
+#define DT_INIT 12
+#define DT_FINI 13
+#define DT_SONAME 14
+#define DT_RPATH 15
+#define DT_SYMBOLIC 16
+#define DT_REL 17
+#define DT_RELSZ 18
+#define DT_RELENT 19
+#define DT_PLTREL 20
+#define DT_DEBUG 21
+#define DT_TEXTREL 22
+#define DT_JMPREL 23
+#define DT_LOPROC 0x70000000
+#define DT_HIPROC 0x7fffffff
diff --git a/gnu/usr.bin/gdb/gdb/elf/dwarf.h b/gnu/usr.bin/gdb/gdb/elf/dwarf.h
new file mode 100644
index 000000000000..bc9723ae04a0
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/elf/dwarf.h
@@ -0,0 +1,314 @@
+/* Declarations and definitions of codes relating to the DWARF symbolic
+ debugging information format.
+
+ Written by Ron Guilmette (rfg@ncd.com)
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file is derived from the DWARF specification (a public document)
+ Revision 1.0.1 (April 8, 1992) developed by the UNIX International
+ Programming Languages Special Interest Group (UI/PLSIG) and distributed
+ by UNIX International. Copies of this specification are available from
+ UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
+*/
+
+/* Tag names and codes. */
+
+enum dwarf_tag {
+ TAG_padding = 0x0000,
+ TAG_array_type = 0x0001,
+ TAG_class_type = 0x0002,
+ TAG_entry_point = 0x0003,
+ TAG_enumeration_type = 0x0004,
+ TAG_formal_parameter = 0x0005,
+ TAG_global_subroutine = 0x0006,
+ TAG_global_variable = 0x0007,
+ /* 0x0008 -- reserved */
+ /* 0x0009 -- reserved */
+ TAG_label = 0x000a,
+ TAG_lexical_block = 0x000b,
+ TAG_local_variable = 0x000c,
+ TAG_member = 0x000d,
+ /* 0x000e -- reserved */
+ TAG_pointer_type = 0x000f,
+ TAG_reference_type = 0x0010,
+ TAG_compile_unit = 0x0011,
+ TAG_string_type = 0x0012,
+ TAG_structure_type = 0x0013,
+ TAG_subroutine = 0x0014,
+ TAG_subroutine_type = 0x0015,
+ TAG_typedef = 0x0016,
+ TAG_union_type = 0x0017,
+ TAG_unspecified_parameters = 0x0018,
+ TAG_variant = 0x0019,
+ TAG_common_block = 0x001a,
+ TAG_common_inclusion = 0x001b,
+ TAG_inheritance = 0x001c,
+ TAG_inlined_subroutine = 0x001d,
+ TAG_module = 0x001e,
+ TAG_ptr_to_member_type = 0x001f,
+ TAG_set_type = 0x0020,
+ TAG_subrange_type = 0x0021,
+ TAG_with_stmt = 0x0022,
+
+ /* GNU extensions */
+
+ TAG_format_label = 0x8000, /* for FORTRAN 77 and Fortran 90 */
+ TAG_namelist = 0x8001, /* For Fortran 90 */
+ TAG_function_template = 0x8002, /* for C++ */
+ TAG_class_template = 0x8003 /* for C++ */
+};
+
+#define TAG_lo_user 0x8000 /* implementation-defined range start */
+#define TAG_hi_user 0xffff /* implementation-defined range end */
+#define TAG_source_file TAG_compile_unit /* for backward compatibility */
+
+/* Form names and codes. */
+
+enum dwarf_form {
+ FORM_ADDR = 0x1,
+ FORM_REF = 0x2,
+ FORM_BLOCK2 = 0x3,
+ FORM_BLOCK4 = 0x4,
+ FORM_DATA2 = 0x5,
+ FORM_DATA4 = 0x6,
+ FORM_DATA8 = 0x7,
+ FORM_STRING = 0x8
+};
+
+/* Attribute names and codes. */
+
+enum dwarf_attribute {
+ AT_sibling = (0x0010|FORM_REF),
+ AT_location = (0x0020|FORM_BLOCK2),
+ AT_name = (0x0030|FORM_STRING),
+ AT_fund_type = (0x0050|FORM_DATA2),
+ AT_mod_fund_type = (0x0060|FORM_BLOCK2),
+ AT_user_def_type = (0x0070|FORM_REF),
+ AT_mod_u_d_type = (0x0080|FORM_BLOCK2),
+ AT_ordering = (0x0090|FORM_DATA2),
+ AT_subscr_data = (0x00a0|FORM_BLOCK2),
+ AT_byte_size = (0x00b0|FORM_DATA4),
+ AT_bit_offset = (0x00c0|FORM_DATA2),
+ AT_bit_size = (0x00d0|FORM_DATA4),
+ /* (0x00e0|FORM_xxxx) -- reserved */
+ AT_element_list = (0x00f0|FORM_BLOCK4),
+ AT_stmt_list = (0x0100|FORM_DATA4),
+ AT_low_pc = (0x0110|FORM_ADDR),
+ AT_high_pc = (0x0120|FORM_ADDR),
+ AT_language = (0x0130|FORM_DATA4),
+ AT_member = (0x0140|FORM_REF),
+ AT_discr = (0x0150|FORM_REF),
+ AT_discr_value = (0x0160|FORM_BLOCK2),
+ /* (0x0170|FORM_xxxx) -- reserved */
+ /* (0x0180|FORM_xxxx) -- reserved */
+ AT_string_length = (0x0190|FORM_BLOCK2),
+ AT_common_reference = (0x01a0|FORM_REF),
+ AT_comp_dir = (0x01b0|FORM_STRING),
+ AT_const_value_string = (0x01c0|FORM_STRING),
+ AT_const_value_data2 = (0x01c0|FORM_DATA2),
+ AT_const_value_data4 = (0x01c0|FORM_DATA4),
+ AT_const_value_data8 = (0x01c0|FORM_DATA8),
+ AT_const_value_block2 = (0x01c0|FORM_BLOCK2),
+ AT_const_value_block4 = (0x01c0|FORM_BLOCK4),
+ AT_containing_type = (0x01d0|FORM_REF),
+ AT_default_value_addr = (0x01e0|FORM_ADDR),
+ AT_default_value_data2 = (0x01e0|FORM_DATA2),
+ AT_default_value_data4 = (0x01e0|FORM_DATA4),
+ AT_default_value_data8 = (0x01e0|FORM_DATA8),
+ AT_default_value_string = (0x01e0|FORM_STRING),
+ AT_friends = (0x01f0|FORM_BLOCK2),
+ AT_inline = (0x0200|FORM_STRING),
+ AT_is_optional = (0x0210|FORM_STRING),
+ AT_lower_bound_ref = (0x0220|FORM_REF),
+ AT_lower_bound_data2 = (0x0220|FORM_DATA2),
+ AT_lower_bound_data4 = (0x0220|FORM_DATA4),
+ AT_lower_bound_data8 = (0x0220|FORM_DATA8),
+ AT_private = (0x0240|FORM_STRING),
+ AT_producer = (0x0250|FORM_STRING),
+ AT_program = (0x0230|FORM_STRING),
+ AT_protected = (0x0260|FORM_STRING),
+ AT_prototyped = (0x0270|FORM_STRING),
+ AT_public = (0x0280|FORM_STRING),
+ AT_pure_virtual = (0x0290|FORM_STRING),
+ AT_return_addr = (0x02a0|FORM_BLOCK2),
+ AT_abstract_origin = (0x02b0|FORM_REF),
+ AT_start_scope = (0x02c0|FORM_DATA4),
+ AT_stride_size = (0x02e0|FORM_DATA4),
+ AT_upper_bound_ref = (0x02f0|FORM_REF),
+ AT_upper_bound_data2 = (0x02f0|FORM_DATA2),
+ AT_upper_bound_data4 = (0x02f0|FORM_DATA4),
+ AT_upper_bound_data8 = (0x02f0|FORM_DATA8),
+ AT_virtual = (0x0300|FORM_STRING),
+
+ /* GNU extensions. */
+
+ AT_sf_names = (0x8000|FORM_DATA4),
+ AT_src_info = (0x8010|FORM_DATA4),
+ AT_mac_info = (0x8020|FORM_DATA4),
+ AT_src_coords = (0x8030|FORM_DATA4),
+ AT_body_begin = (0x8040|FORM_ADDR),
+ AT_body_end = (0x8050|FORM_ADDR)
+};
+
+#define AT_lo_user 0x8000 /* implementation-defined range start */
+#define AT_hi_user 0xffff /* implementation-defined range end */
+
+/* Location atom names and codes. */
+
+enum dwarf_location_atom {
+ OP_REG = 0x01,
+ OP_BASEREG = 0x02,
+ OP_ADDR = 0x03,
+ OP_CONST = 0x04,
+ OP_DEREF2 = 0x05,
+ OP_DEREF4 = 0x06,
+ OP_ADD = 0x07
+};
+
+#define OP_LO_USER 0x80 /* implementation-defined range start */
+#define OP_HI_USER 0xff /* implementation-defined range end */
+
+/* Fundamental type names and codes. */
+
+enum dwarf_fundamental_type {
+ FT_char = 0x0001,
+ FT_signed_char = 0x0002,
+ FT_unsigned_char = 0x0003,
+ FT_short = 0x0004,
+ FT_signed_short = 0x0005,
+ FT_unsigned_short = 0x0006,
+ FT_integer = 0x0007,
+ FT_signed_integer = 0x0008,
+ FT_unsigned_integer = 0x0009,
+ FT_long = 0x000a,
+ FT_signed_long = 0x000b,
+ FT_unsigned_long = 0x000c,
+ FT_pointer = 0x000d, /* an alias for (void *) */
+ FT_float = 0x000e,
+ FT_dbl_prec_float = 0x000f,
+ FT_ext_prec_float = 0x0010, /* breaks "classic" svr4 SDB */
+ FT_complex = 0x0011, /* breaks "classic" svr4 SDB */
+ FT_dbl_prec_complex = 0x0012, /* breaks "classic" svr4 SDB */
+ /* 0x0013 -- reserved */
+ FT_void = 0x0014,
+ FT_boolean = 0x0015, /* breaks "classic" svr4 SDB */
+ FT_ext_prec_complex = 0x0016, /* breaks "classic" svr4 SDB */
+ FT_label = 0x0017,
+
+ /* GNU extensions
+ The low order byte must indicate the size (in bytes) for the type.
+ All of these types will probably break "classic" svr4 SDB */
+
+ FT_long_long = 0x8008,
+ FT_signed_long_long = 0x8108,
+ FT_unsigned_long_long = 0x8208,
+
+ FT_int8 = 0x9001,
+ FT_signed_int8 = 0x9101,
+ FT_unsigned_int8 = 0x9201,
+ FT_int16 = 0x9302,
+ FT_signed_int16 = 0x9402,
+ FT_unsigned_int16 = 0x9502,
+ FT_int32 = 0x9604,
+ FT_signed_int32 = 0x9704,
+ FT_unsigned_int32 = 0x9804,
+ FT_int64 = 0x9908,
+ FT_signed_int64 = 0x9a08,
+ FT_unsigned_int64 = 0x9b08,
+
+ FT_real32 = 0xa004,
+ FT_real64 = 0xa108,
+ FT_real96 = 0xa20c,
+ FT_real128 = 0xa310
+};
+
+#define FT_lo_user 0x8000 /* implementation-defined range start */
+#define FT_hi_user 0xffff /* implementation defined range end */
+
+/* Type modifier names and codes. */
+
+enum dwarf_type_modifier {
+ MOD_pointer_to = 0x01,
+ MOD_reference_to = 0x02,
+ MOD_const = 0x03,
+ MOD_volatile = 0x04
+};
+
+#define MOD_lo_user 0x80 /* implementation-defined range start */
+#define MOD_hi_user 0xff /* implementation-defined range end */
+
+/* Array ordering names and codes. */
+
+enum dwarf_array_dim_ordering {
+ ORD_row_major = 0,
+ ORD_col_major = 1
+};
+
+/* Array subscript format names and codes. */
+
+enum dwarf_subscr_data_formats {
+ FMT_FT_C_C = 0x0,
+ FMT_FT_C_X = 0x1,
+ FMT_FT_X_C = 0x2,
+ FMT_FT_X_X = 0x3,
+ FMT_UT_C_C = 0x4,
+ FMT_UT_C_X = 0x5,
+ FMT_UT_X_C = 0x6,
+ FMT_UT_X_X = 0x7,
+ FMT_ET = 0x8
+};
+
+/* Derived from above for ease of use. */
+
+#define FMT_CODE(_FUNDAMENTAL_TYPE_P, _UB_CONST_P, _LB_CONST_P) \
+ (((_FUNDAMENTAL_TYPE_P) ? 0 : 4) \
+ | ((_UB_CONST_P) ? 0 : 2) \
+ | ((_LB_CONST_P) ? 0 : 1))
+
+/* Source language names and codes. */
+
+enum dwarf_source_language {
+ LANG_C89 = 0x00000001,
+ LANG_C = 0x00000002,
+ LANG_ADA83 = 0x00000003,
+ LANG_C_PLUS_PLUS = 0x00000004,
+ LANG_COBOL74 = 0x00000005,
+ LANG_COBOL85 = 0x00000006,
+ LANG_FORTRAN77 = 0x00000007,
+ LANG_FORTRAN90 = 0x00000008,
+ LANG_PASCAL83 = 0x00000009,
+ LANG_MODULA2 = 0x0000000a,
+
+ /* GNU extensions */
+
+ LANG_CHILL = 0x00009af3 /* random value for GNU Chill */
+};
+
+#define LANG_lo_user 0x00008000 /* implementation-defined range start */
+#define LANG_hi_user 0x0000ffff /* implementation-defined range end */
+
+/* Names and codes for GNU "macinfo" extension. */
+
+enum dwarf_macinfo_record_type {
+ MACINFO_start = 's',
+ MACINFO_resume = 'r',
+ MACINFO_define = 'd',
+ MACINFO_undef = 'u'
+};
diff --git a/gnu/usr.bin/gdb/gdb/elf/external.h b/gnu/usr.bin/gdb/gdb/elf/external.h
new file mode 100644
index 000000000000..f2ab63e1ede4
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/elf/external.h
@@ -0,0 +1,190 @@
+/* ELF support for BFD.
+ Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ Cygnus Support, from information published
+ in "UNIX System V Release 4, Programmers Guide: ANSI C and
+ Programming Support Tools".
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This file is part of ELF support for BFD, and contains the portions
+ that describe how ELF is represented externally by the BFD library.
+ I.E. it describes the in-file representation of ELF. It requires
+ the elf-common.h file which contains the portions that are common to
+ both the internal and external representations. */
+
+/* The 64-bit stuff is kind of random. Perhaps someone will publish a
+ spec someday. */
+
+/* ELF Header (32-bit implementations) */
+
+typedef struct {
+ unsigned char e_ident[16]; /* ELF "magic number" */
+ unsigned char e_type[2]; /* Identifies object file type */
+ unsigned char e_machine[2]; /* Specifies required architecture */
+ unsigned char e_version[4]; /* Identifies object file version */
+ unsigned char e_entry[4]; /* Entry point virtual address */
+ unsigned char e_phoff[4]; /* Program header table file offset */
+ unsigned char e_shoff[4]; /* Section header table file offset */
+ unsigned char e_flags[4]; /* Processor-specific flags */
+ unsigned char e_ehsize[2]; /* ELF header size in bytes */
+ unsigned char e_phentsize[2]; /* Program header table entry size */
+ unsigned char e_phnum[2]; /* Program header table entry count */
+ unsigned char e_shentsize[2]; /* Section header table entry size */
+ unsigned char e_shnum[2]; /* Section header table entry count */
+ unsigned char e_shstrndx[2]; /* Section header string table index */
+} Elf32_External_Ehdr;
+
+typedef struct {
+ unsigned char e_ident[16]; /* ELF "magic number" */
+ unsigned char e_type[2]; /* Identifies object file type */
+ unsigned char e_machine[2]; /* Specifies required architecture */
+ unsigned char e_version[4]; /* Identifies object file version */
+ unsigned char e_entry[8]; /* Entry point virtual address */
+ unsigned char e_phoff[8]; /* Program header table file offset */
+ unsigned char e_shoff[8]; /* Section header table file offset */
+ unsigned char e_flags[4]; /* Processor-specific flags */
+ unsigned char e_ehsize[2]; /* ELF header size in bytes */
+ unsigned char e_phentsize[2]; /* Program header table entry size */
+ unsigned char e_phnum[2]; /* Program header table entry count */
+ unsigned char e_shentsize[2]; /* Section header table entry size */
+ unsigned char e_shnum[2]; /* Section header table entry count */
+ unsigned char e_shstrndx[2]; /* Section header string table index */
+} Elf64_External_Ehdr;
+
+/* Program header */
+
+typedef struct {
+ unsigned char p_type[4]; /* Identifies program segment type */
+ unsigned char p_offset[4]; /* Segment file offset */
+ unsigned char p_vaddr[4]; /* Segment virtual address */
+ unsigned char p_paddr[4]; /* Segment physical address */
+ unsigned char p_filesz[4]; /* Segment size in file */
+ unsigned char p_memsz[4]; /* Segment size in memory */
+ unsigned char p_flags[4]; /* Segment flags */
+ unsigned char p_align[4]; /* Segment alignment, file & memory */
+} Elf32_External_Phdr;
+
+typedef struct {
+ unsigned char p_type[4]; /* Identifies program segment type */
+ unsigned char p_flags[4]; /* Segment flags */
+ unsigned char p_offset[8]; /* Segment file offset */
+ unsigned char p_vaddr[8]; /* Segment virtual address */
+ unsigned char p_paddr[8]; /* Segment physical address */
+ unsigned char p_filesz[8]; /* Segment size in file */
+ unsigned char p_memsz[8]; /* Segment size in memory */
+ unsigned char p_align[8]; /* Segment alignment, file & memory */
+} Elf64_External_Phdr;
+
+/* Section header */
+
+typedef struct {
+ unsigned char sh_name[4]; /* Section name, index in string tbl */
+ unsigned char sh_type[4]; /* Type of section */
+ unsigned char sh_flags[4]; /* Miscellaneous section attributes */
+ unsigned char sh_addr[4]; /* Section virtual addr at execution */
+ unsigned char sh_offset[4]; /* Section file offset */
+ unsigned char sh_size[4]; /* Size of section in bytes */
+ unsigned char sh_link[4]; /* Index of another section */
+ unsigned char sh_info[4]; /* Additional section information */
+ unsigned char sh_addralign[4]; /* Section alignment */
+ unsigned char sh_entsize[4]; /* Entry size if section holds table */
+} Elf32_External_Shdr;
+
+typedef struct {
+ unsigned char sh_name[4]; /* Section name, index in string tbl */
+ unsigned char sh_type[4]; /* Type of section */
+ unsigned char sh_flags[8]; /* Miscellaneous section attributes */
+ unsigned char sh_addr[8]; /* Section virtual addr at execution */
+ unsigned char sh_offset[8]; /* Section file offset */
+ unsigned char sh_size[8]; /* Size of section in bytes */
+ unsigned char sh_link[4]; /* Index of another section */
+ unsigned char sh_info[4]; /* Additional section information */
+ unsigned char sh_addralign[8]; /* Section alignment */
+ unsigned char sh_entsize[8]; /* Entry size if section holds table */
+} Elf64_External_Shdr;
+
+/* Symbol table entry */
+
+typedef struct {
+ unsigned char st_name[4]; /* Symbol name, index in string tbl */
+ unsigned char st_value[4]; /* Value of the symbol */
+ unsigned char st_size[4]; /* Associated symbol size */
+ unsigned char st_info[1]; /* Type and binding attributes */
+ unsigned char st_other[1]; /* No defined meaning, 0 */
+ unsigned char st_shndx[2]; /* Associated section index */
+} Elf32_External_Sym;
+
+typedef struct {
+ unsigned char st_name[4]; /* Symbol name, index in string tbl */
+ unsigned char st_info[1]; /* Type and binding attributes */
+ unsigned char st_other[1]; /* No defined meaning, 0 */
+ unsigned char st_shndx[2]; /* Associated section index */
+ unsigned char st_value[8]; /* Value of the symbol */
+ unsigned char st_size[8]; /* Associated symbol size */
+} Elf64_External_Sym;
+
+/* Note segments */
+
+typedef struct {
+ unsigned char namesz[4]; /* Size of entry's owner string */
+ unsigned char descsz[4]; /* Size of the note descriptor */
+ unsigned char type[4]; /* Interpretation of the descriptor */
+ char name[1]; /* Start of the name+desc data */
+} Elf_External_Note;
+
+/* Relocation Entries */
+typedef struct {
+ unsigned char r_offset[4]; /* Location at which to apply the action */
+ unsigned char r_info[4]; /* index and type of relocation */
+} Elf32_External_Rel;
+
+typedef struct {
+ unsigned char r_offset[4]; /* Location at which to apply the action */
+ unsigned char r_info[4]; /* index and type of relocation */
+ unsigned char r_addend[4]; /* Constant addend used to compute value */
+} Elf32_External_Rela;
+
+typedef struct {
+ unsigned char r_offset[8]; /* Location at which to apply the action */
+ unsigned char r_info[8]; /* index and type of relocation */
+} Elf64_External_Rel;
+
+typedef struct {
+ unsigned char r_offset[8]; /* Location at which to apply the action */
+ unsigned char r_info[8]; /* index and type of relocation */
+ unsigned char r_addend[8]; /* Constant addend used to compute value */
+} Elf64_External_Rela;
+
+/* dynamic section structure */
+
+typedef struct {
+ unsigned char d_tag[4]; /* entry tag value */
+ union {
+ unsigned char d_val[4];
+ unsigned char d_ptr[4];
+ } d_un;
+} Elf32_External_Dyn;
+
+typedef struct {
+ unsigned char d_tag[8]; /* entry tag value */
+ union {
+ unsigned char d_val[8];
+ unsigned char d_ptr[8];
+ } d_un;
+} Elf64_External_Dyn;
diff --git a/gnu/usr.bin/gdb/gdb/elf/internal.h b/gnu/usr.bin/gdb/gdb/elf/internal.h
new file mode 100644
index 000000000000..ae4bdada5ea9
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/elf/internal.h
@@ -0,0 +1,195 @@
+/* ELF support for BFD.
+ Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ Cygnus Support, from information published
+ in "UNIX System V Release 4, Programmers Guide: ANSI C and
+ Programming Support Tools".
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This file is part of ELF support for BFD, and contains the portions
+ that describe how ELF is represented internally in the BFD library.
+ I.E. it describes the in-memory representation of ELF. It requires
+ the elf-common.h file which contains the portions that are common to
+ both the internal and external representations. */
+
+/* Types used by various structures, functions, etc. */
+
+typedef unsigned long Elf32_Addr; /* Unsigned program address */
+typedef unsigned long Elf32_Off; /* Unsigned file offset */
+typedef long Elf32_Sword; /* Signed large integer */
+typedef unsigned long Elf32_Word; /* Unsigned large integer */
+typedef unsigned short Elf32_Half; /* Unsigned medium integer */
+typedef unsigned char Elf32_Char; /* Unsigned tiny integer */
+
+#ifdef HOST_64_BIT
+typedef unsigned HOST_64_BIT Elf64_Addr;
+typedef unsigned HOST_64_BIT Elf64_Off;
+typedef HOST_64_BIT Elf64_Sxword;
+typedef unsigned HOST_64_BIT Elf64_Xword;
+#endif
+typedef long Elf64_Sword;
+typedef unsigned long Elf64_Word;
+typedef unsigned short Elf64_Half;
+
+/* NOTE that these structures are not kept in the same order as they appear
+ in the object file. In some cases they've been reordered for more optimal
+ packing under various circumstances. */
+
+/* ELF Header */
+
+#define EI_NIDENT 16 /* Size of e_ident[] */
+
+typedef struct elf_internal_ehdr {
+ unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
+ bfd_vma e_entry; /* Entry point virtual address */
+ bfd_signed_vma e_phoff; /* Program header table file offset */
+ bfd_signed_vma e_shoff; /* Section header table file offset */
+ unsigned long e_version; /* Identifies object file version */
+ unsigned long e_flags; /* Processor-specific flags */
+ unsigned short e_type; /* Identifies object file type */
+ unsigned short e_machine; /* Specifies required architecture */
+ unsigned short e_ehsize; /* ELF header size in bytes */
+ unsigned short e_phentsize; /* Program header table entry size */
+ unsigned short e_phnum; /* Program header table entry count */
+ unsigned short e_shentsize; /* Section header table entry size */
+ unsigned short e_shnum; /* Section header table entry count */
+ unsigned short e_shstrndx; /* Section header string table index */
+} Elf_Internal_Ehdr;
+
+#define elf32_internal_ehdr elf_internal_ehdr
+#define Elf32_Internal_Ehdr Elf_Internal_Ehdr
+#define elf64_internal_ehdr elf_internal_ehdr
+#define Elf64_Internal_Ehdr Elf_Internal_Ehdr
+
+/* Program header */
+
+struct elf_internal_phdr {
+ unsigned long p_type; /* Identifies program segment type */
+ unsigned long p_flags; /* Segment flags */
+ bfd_vma p_offset; /* Segment file offset */
+ bfd_vma p_vaddr; /* Segment virtual address */
+ bfd_vma p_paddr; /* Segment physical address */
+ bfd_vma p_filesz; /* Segment size in file */
+ bfd_vma p_memsz; /* Segment size in memory */
+ bfd_vma p_align; /* Segment alignment, file & memory */
+};
+
+typedef struct elf_internal_phdr Elf_Internal_Phdr;
+#define elf32_internal_phdr elf_internal_phdr
+#define Elf32_Internal_Phdr Elf_Internal_Phdr
+#define elf64_internal_phdr elf_internal_phdr
+#define Elf64_Internal_Phdr Elf_Internal_Phdr
+
+/* Section header */
+
+typedef struct elf_internal_shdr {
+ unsigned int sh_name; /* Section name, index in string tbl */
+ unsigned int sh_type; /* Type of section */
+ bfd_vma sh_flags; /* Miscellaneous section attributes */
+ bfd_vma sh_addr; /* Section virtual addr at execution */
+ bfd_size_type sh_size; /* Size of section in bytes */
+ bfd_size_type sh_entsize; /* Entry size if section holds table */
+ unsigned long sh_link; /* Index of another section */
+ unsigned long sh_info; /* Additional section information */
+ file_ptr sh_offset; /* Section file offset */
+ unsigned int sh_addralign; /* Section alignment */
+
+ /* The internal rep also has some cached info associated with it. */
+ void *rawdata; /* null if unused... */
+ void *contents; /* null if unused... */
+ bfd_vma size; /* size of contents (0 if unused) */
+} Elf_Internal_Shdr;
+
+#define elf32_internal_shdr elf_internal_shdr
+#define Elf32_Internal_Shdr Elf_Internal_Shdr
+#define elf64_internal_shdr elf_internal_shdr
+#define Elf64_Internal_Shdr Elf_Internal_Shdr
+
+/* Symbol table entry */
+
+struct elf_internal_sym {
+ bfd_vma st_value; /* Value of the symbol */
+ bfd_vma st_size; /* Associated symbol size */
+ unsigned long st_name; /* Symbol name, index in string tbl */
+ unsigned char st_info; /* Type and binding attributes */
+ unsigned char st_other; /* No defined meaning, 0 */
+ unsigned short st_shndx; /* Associated section index */
+};
+
+typedef struct elf_internal_sym Elf_Internal_Sym;
+
+#define elf32_internal_sym elf_internal_sym
+#define elf64_internal_sym elf_internal_sym
+#define Elf32_Internal_Sym Elf_Internal_Sym
+#define Elf64_Internal_Sym Elf_Internal_Sym
+
+/* Note segments */
+
+typedef struct elf_internal_note {
+ unsigned long namesz; /* Size of entry's owner string */
+ unsigned long descsz; /* Size of the note descriptor */
+ unsigned long type; /* Interpretation of the descriptor */
+ char name[1]; /* Start of the name+desc data */
+} Elf_Internal_Note;
+#define Elf32_Internal_Note Elf_Internal_Note
+#define elf32_internal_note elf_internal_note
+
+/* Relocation Entries */
+
+typedef struct elf_internal_rel {
+ bfd_vma r_offset; /* Location at which to apply the action */
+ /* This needs to support 64-bit values in elf64. */
+ bfd_vma r_info; /* index and type of relocation */
+} Elf_Internal_Rel;
+
+#define elf32_internal_rel elf_internal_rel
+#define Elf32_Internal_Rel Elf_Internal_Rel
+#define elf64_internal_rel elf_internal_rel
+#define Elf64_Internal_Rel Elf_Internal_Rel
+
+typedef struct elf_internal_rela {
+ bfd_vma r_offset; /* Location at which to apply the action */
+ bfd_vma r_info; /* Index and Type of relocation */
+ bfd_signed_vma r_addend; /* Constant addend used to compute value */
+} Elf_Internal_Rela;
+
+#define elf32_internal_rela elf_internal_rela
+#define elf64_internal_rela elf_internal_rela
+#define Elf32_Internal_Rela Elf_Internal_Rela
+#define Elf64_Internal_Rela Elf_Internal_Rela
+
+/* dynamic section structure */
+
+typedef struct {
+ Elf32_Sword d_tag; /* entry tag value */
+ union {
+ Elf32_Word d_val;
+ Elf32_Addr d_ptr;
+ } d_un;
+} Elf32_Internal_Dyn;
+
+#ifdef HOST_64_BIT
+typedef struct {
+ Elf64_Xword d_tag; /* entry tag value */
+ union {
+ Elf64_Xword d_val;
+ Elf64_Addr d_ptr;
+ } d_un;
+} Elf64_Internal_Dyn;
+#endif
diff --git a/gnu/usr.bin/gdb/gdb/elfread.c b/gnu/usr.bin/gdb/gdb/elfread.c
new file mode 100644
index 000000000000..230afecefb2e
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/elfread.c
@@ -0,0 +1,729 @@
+/* Read ELF (Executable and Linking Format) object files for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include <time.h> /* For time_t in libbfd.h. */
+#include <sys/types.h> /* For time_t, if not in time.h. */
+#include "libbfd.h" /* For bfd_elf_find_section */
+#include "libelf.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+#include "complaints.h"
+#include <string.h>
+#include "demangle.h"
+
+/* The struct elfinfo is available only during ELF symbol table and
+ psymtab reading. It is destroyed at the complation of psymtab-reading.
+ It's local to elf_symfile_read. */
+
+struct elfinfo {
+ file_ptr dboffset; /* Offset to dwarf debug section */
+ unsigned int dbsize; /* Size of dwarf debug section */
+ file_ptr lnoffset; /* Offset to dwarf line number section */
+ unsigned int lnsize; /* Size of dwarf line number section */
+ asection *stabsect; /* Section pointer for .stab section */
+ asection *stabindexsect; /* Section pointer for .stab.index section */
+};
+
+/* Various things we might complain about... */
+
+struct complaint section_info_complaint =
+ {"elf/stab section information %s without a preceding file symbol", 0, 0};
+
+struct complaint section_info_dup_complaint =
+ {"duplicated elf/stab section information for %s", 0, 0};
+
+struct complaint stab_info_mismatch_complaint =
+ {"elf/stab section information missing for %s", 0, 0};
+
+struct complaint stab_info_questionable_complaint =
+ {"elf/stab section information questionable for %s", 0, 0};
+
+static void
+elf_symfile_init PARAMS ((struct objfile *));
+
+static void
+elf_new_init PARAMS ((struct objfile *));
+
+static void
+elf_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+elf_symfile_finish PARAMS ((struct objfile *));
+
+static void
+elf_symtab_read PARAMS ((bfd *, CORE_ADDR, struct objfile *));
+
+static void
+free_elfinfo PARAMS ((void *));
+
+static struct section_offsets *
+elf_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+static void
+record_minimal_symbol_and_info PARAMS ((char *, CORE_ADDR,
+ enum minimal_symbol_type, char *,
+ struct objfile *));
+
+static void
+elf_locate_sections PARAMS ((bfd *, asection *, void *));
+
+/* We are called once per section from elf_symfile_read. We
+ need to examine each section we are passed, check to see
+ if it is something we are interested in processing, and
+ if so, stash away some access information for the section.
+
+ For now we recognize the dwarf debug information sections and
+ line number sections from matching their section names. The
+ ELF definition is no real help here since it has no direct
+ knowledge of DWARF (by design, so any debugging format can be
+ used).
+
+ We also recognize the ".stab" sections used by the Sun compilers
+ released with Solaris 2.
+
+ FIXME: The section names should not be hardwired strings (what
+ should they be? I don't think most object file formats have enough
+ section flags to specify what kind of debug section it is
+ -kingdon). */
+
+static void
+elf_locate_sections (ignore_abfd, sectp, eip)
+ bfd *ignore_abfd;
+ asection *sectp;
+ PTR eip;
+{
+ register struct elfinfo *ei;
+
+ ei = (struct elfinfo *) eip;
+ if (STREQ (sectp -> name, ".debug"))
+ {
+ ei -> dboffset = sectp -> filepos;
+ ei -> dbsize = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp -> name, ".line"))
+ {
+ ei -> lnoffset = sectp -> filepos;
+ ei -> lnsize = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp -> name, ".stab"))
+ {
+ ei -> stabsect = sectp;
+ }
+ else if (STREQ (sectp -> name, ".stab.index"))
+ {
+ ei -> stabindexsect = sectp;
+ }
+}
+
+#if 0 /* Currently unused */
+
+char *
+elf_interpreter (abfd)
+ bfd *abfd;
+{
+ sec_ptr interp_sec;
+ unsigned size;
+ char *interp = NULL;
+
+ interp_sec = bfd_get_section_by_name (abfd, ".interp");
+ if (interp_sec)
+ {
+ size = bfd_section_size (abfd, interp_sec);
+ interp = alloca (size);
+ if (bfd_get_section_contents (abfd, interp_sec, interp, (file_ptr)0,
+ size))
+ {
+ interp = savestring (interp, size - 1);
+ }
+ else
+ {
+ interp = NULL;
+ }
+ }
+ return (interp);
+}
+
+#endif
+
+static void
+record_minimal_symbol_and_info (name, address, ms_type, info, objfile)
+ char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ char *info; /* FIXME, is this really char *? */
+ struct objfile *objfile;
+{
+ int section;
+
+ /* Guess the section from the type. This is likely to be wrong in
+ some cases. */
+ switch (ms_type)
+ {
+ case mst_text:
+ case mst_file_text:
+ section = SECT_OFF_TEXT;
+ break;
+ case mst_data:
+ case mst_file_data:
+ section = SECT_OFF_DATA;
+ break;
+ case mst_bss:
+ case mst_file_bss:
+ section = SECT_OFF_BSS;
+ break;
+ default:
+ section = -1;
+ break;
+ }
+
+ name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
+ prim_record_minimal_symbol_and_info (name, address, ms_type, info, section);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ elf_symtab_read -- read the symbol table of an ELF file
+
+SYNOPSIS
+
+ void elf_symtab_read (bfd *abfd, CORE_ADDR addr,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given an open bfd, a base address to relocate symbols to, and a
+ flag that specifies whether or not this bfd is for an executable
+ or not (may be shared library for example), add all the global
+ function and data symbols to the minimal symbol table.
+
+ In stabs-in-ELF, as implemented by Sun, there are some local symbols
+ defined in the ELF symbol table, which can be used to locate
+ the beginnings of sections from each ".o" file that was linked to
+ form the executable objfile. We gather any such info and record it
+ in data structures hung off the objfile's private data.
+
+*/
+
+static void
+elf_symtab_read (abfd, addr, objfile)
+ bfd *abfd;
+ CORE_ADDR addr;
+ struct objfile *objfile;
+{
+ unsigned int storage_needed;
+ asymbol *sym;
+ asymbol **symbol_table;
+ unsigned int number_of_symbols;
+ unsigned int i;
+ int index;
+ struct cleanup *back_to;
+ CORE_ADDR symaddr;
+ enum minimal_symbol_type ms_type;
+ /* If sectinfo is nonNULL, it contains section info that should end up
+ filed in the objfile. */
+ struct stab_section_info *sectinfo = NULL;
+ /* If filesym is nonzero, it points to a file symbol, but we haven't
+ seen any section info for it yet. */
+ asymbol *filesym = 0;
+ struct dbx_symfile_info *dbx = (struct dbx_symfile_info *)
+ objfile->sym_stab_info;
+ unsigned long size;
+
+ storage_needed = get_symtab_upper_bound (abfd);
+ if (storage_needed > 0)
+ {
+ symbol_table = (asymbol **) xmalloc (storage_needed);
+ back_to = make_cleanup (free, symbol_table);
+ number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ sym = symbol_table[i];
+ if (sym -> name == NULL || *sym -> name == '\0')
+ {
+ /* Skip names that don't exist (shouldn't happen), or names
+ that are null strings (may happen). */
+ continue;
+ }
+ if (sym -> flags & BSF_FILE)
+ {
+ /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
+ Chain any old one onto the objfile; remember new sym. */
+ if (sectinfo != NULL)
+ {
+ sectinfo -> next = dbx -> stab_section_info;
+ dbx -> stab_section_info = sectinfo;
+ sectinfo = NULL;
+ }
+ filesym = sym;
+ }
+ else if (sym -> flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
+ {
+ /* Select global/local/weak symbols. Note that bfd puts abs
+ symbols in their own section, so all symbols we are
+ interested in will have a section. */
+ /* Bfd symbols are section relative. */
+ symaddr = sym -> value + sym -> section -> vma;
+ /* Relocate all non-absolute symbols by base address. */
+ if (sym -> section != &bfd_abs_section)
+ {
+ symaddr += addr;
+ }
+ /* For non-absolute symbols, use the type of the section
+ they are relative to, to intuit text/data. Bfd provides
+ no way of figuring this out for absolute symbols. */
+ if (sym -> section == &bfd_abs_section)
+ {
+ ms_type = mst_abs;
+ }
+ else if (sym -> section -> flags & SEC_CODE)
+ {
+ if (sym -> flags & BSF_GLOBAL)
+ {
+ ms_type = mst_text;
+ }
+ else if (sym->name[0] == '.' && sym->name[1] == 'L')
+ /* Looks like a compiler-generated label. Skip it.
+ The assembler should be skipping these (to keep
+ executables small), but apparently with gcc on the
+ delta m88k SVR4, it loses. So to have us check too
+ should be harmless (but I encourage people to fix this
+ in the assembler instead of adding checks here). */
+ continue;
+ else
+ {
+ ms_type = mst_file_text;
+ }
+ }
+ else if (sym -> section -> flags & SEC_ALLOC)
+ {
+ if (sym -> flags & BSF_GLOBAL)
+ {
+ if (sym -> section -> flags & SEC_LOAD)
+ {
+ ms_type = mst_data;
+ }
+ else
+ {
+ ms_type = mst_bss;
+ }
+ }
+ else if (sym -> flags & BSF_LOCAL)
+ {
+ /* Named Local variable in a Data section. Check its
+ name for stabs-in-elf. The STREQ macro checks the
+ first character inline, so we only actually do a
+ strcmp function call on names that start with 'B'
+ or 'D' */
+ index = SECT_OFF_MAX;
+ if (STREQ ("Bbss.bss", sym -> name))
+ {
+ index = SECT_OFF_BSS;
+ }
+ else if (STREQ ("Ddata.data", sym -> name))
+ {
+ index = SECT_OFF_DATA;
+ }
+ else if (STREQ ("Drodata.rodata", sym -> name))
+ {
+ index = SECT_OFF_RODATA;
+ }
+ if (index != SECT_OFF_MAX)
+ {
+ /* Found a special local symbol. Allocate a
+ sectinfo, if needed, and fill it in. */
+ if (sectinfo == NULL)
+ {
+ sectinfo = (struct stab_section_info *)
+ xmmalloc (objfile -> md, sizeof (*sectinfo));
+ memset ((PTR) sectinfo, 0, sizeof (*sectinfo));
+ if (filesym == NULL)
+ {
+ complain (&section_info_complaint,
+ sym -> name);
+ }
+ else
+ {
+ sectinfo -> filename =
+ (char *) filesym -> name;
+ }
+ }
+ if (sectinfo -> sections[index] != 0)
+ {
+ complain (&section_info_dup_complaint,
+ sectinfo -> filename);
+ }
+ /* Bfd symbols are section relative. */
+ symaddr = sym -> value + sym -> section -> vma;
+ /* Relocate non-absolute symbols by base address. */
+ if (sym -> section != &bfd_abs_section)
+ {
+ symaddr += addr;
+ }
+ sectinfo -> sections[index] = symaddr;
+ /* The special local symbols don't go in the
+ minimal symbol table, so ignore this one. */
+ continue;
+ }
+ /* Not a special stabs-in-elf symbol, do regular
+ symbol processing. */
+ if (sym -> section -> flags & SEC_LOAD)
+ {
+ ms_type = mst_file_data;
+ }
+ else
+ {
+ ms_type = mst_file_bss;
+ }
+ }
+ else
+ {
+ ms_type = mst_unknown;
+ }
+ }
+ else
+ {
+ /* FIXME: Solaris2 shared libraries include lots of
+ odd "absolute" and "undefined" symbols, that play
+ hob with actions like finding what function the PC
+ is in. Ignore them if they aren't text, data, or bss. */
+ /* ms_type = mst_unknown; */
+ continue; /* Skip this symbol. */
+ }
+ /* Pass symbol size field in via BFD. FIXME!!! */
+ size = ((elf_symbol_type *) sym) -> internal_elf_sym.st_size;
+ record_minimal_symbol_and_info ((char *) sym -> name, symaddr,
+ ms_type, (PTR) size, objfile);
+ }
+ }
+ do_cleanups (back_to);
+ }
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to elf_symfile_init, which
+ currently does nothing.
+
+ SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
+ in each section. We simplify it down to a single offset for all
+ symbols. FIXME.
+
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file).
+
+ This function only does the minimum work necessary for letting the
+ user "name" things symbolically; it does not read the entire symtab.
+ Instead, it reads the external and static symbols and puts 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 symbols
+ for real.
+
+ We look for sections with specific names, to tell us what debug
+ format to look for: FIXME!!!
+
+ dwarf_build_psymtabs() builds psymtabs for DWARF symbols;
+ elfstab_build_psymtabs() handles STABS symbols.
+
+ Note that ELF files have a "minimal" symbol table, which looks a lot
+ like a COFF symbol table, but has only the minimal information necessary
+ for linking. We process this also, and use the information to
+ build gdb's minimal symbol table. This gives us some minimal debugging
+ capability even for files compiled without -g. */
+
+static void
+elf_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ bfd *abfd = objfile->obfd;
+ struct elfinfo ei;
+ struct cleanup *back_to;
+ CORE_ADDR offset;
+
+ init_minimal_symbol_collection ();
+ back_to = make_cleanup (discard_minimal_symbols, 0);
+
+ memset ((char *) &ei, 0, sizeof (ei));
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_stab_info = (PTR)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+ memset ((char *) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info));
+ make_cleanup (free_elfinfo, (PTR) objfile);
+
+ /* Process the normal ELF symbol table first. This may write some
+ chain of info into the dbx_symfile_info in objfile->sym_stab_info,
+ which can later be used by elfstab_offset_sections. */
+
+ /* FIXME, should take a section_offsets param, not just an offset. */
+ offset = ANOFFSET (section_offsets, 0);
+ elf_symtab_read (abfd, offset, objfile);
+
+ /* Now process debugging information, which is contained in
+ special ELF sections. We first have to find them... */
+
+ bfd_map_over_sections (abfd, elf_locate_sections, (PTR) &ei);
+ if (ei.dboffset && ei.lnoffset)
+ {
+ /* DWARF sections */
+ dwarf_build_psymtabs (objfile,
+ section_offsets, mainline,
+ ei.dboffset, ei.dbsize,
+ ei.lnoffset, ei.lnsize);
+ }
+ if (ei.stabsect)
+ {
+ /* STABS sections */
+
+ /* FIXME: Sun didn't really know how to implement this well.
+ They made .stab sections that don't point to the .stabstr
+ section with the sh_link field. BFD doesn't make string table
+ sections visible to the caller. So we have to search the
+ ELF section table, not the BFD section table, for the string
+ table. */
+ struct elf32_internal_shdr *elf_sect;
+
+ elf_sect = bfd_elf_find_section (abfd, ".stabstr");
+ if (elf_sect)
+ elfstab_build_psymtabs (objfile,
+ section_offsets,
+ mainline,
+ ei.stabsect->filepos, /* .stab offset */
+ bfd_get_section_size_before_reloc (ei.stabsect),/* .stab size */
+ (file_ptr) elf_sect->sh_offset, /* .stabstr offset */
+ elf_sect->sh_size); /* .stabstr size */
+ }
+
+ if (!have_partial_symbols ())
+ {
+ wrap_here ("");
+ printf_filtered ("(no debugging symbols found)...");
+ wrap_here ("");
+ }
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ do_cleanups (back_to);
+}
+
+/* This cleans up the objfile's sym_stab_info pointer, and the chain of
+ stab_section_info's, that might be dangling from it. */
+
+static void
+free_elfinfo (objp)
+ PTR objp;
+{
+ struct objfile *objfile = (struct objfile *)objp;
+ struct dbx_symfile_info *dbxinfo = (struct dbx_symfile_info *)
+ objfile->sym_stab_info;
+ struct stab_section_info *ssi, *nssi;
+
+ ssi = dbxinfo->stab_section_info;
+ while (ssi)
+ {
+ nssi = ssi->next;
+ mfree (objfile->md, ssi);
+ ssi = nssi;
+ }
+
+ dbxinfo->stab_section_info = 0; /* Just say No mo info about this. */
+}
+
+
+/* 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).
+
+ We reinitialize buildsym, since we may be reading stabs from an ELF file. */
+
+static void
+elf_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+/* Perform any local cleanups required when we are done with a particular
+ objfile. I.E, we are in the process of discarding all symbol information
+ for an objfile, freeing up all memory held for it, and unlinking the
+ objfile struct from the global list of known objfiles. */
+
+static void
+elf_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_stab_info != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_stab_info);
+ }
+}
+
+/* ELF specific initialization routine for reading symbols.
+
+ It is passed a pointer to 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 can fill with goodies.
+
+ For now at least, we have nothing in particular to do, so this function is
+ just a stub. */
+
+static void
+elf_symfile_init (ignore)
+ struct objfile *ignore;
+{
+}
+
+/* ELF specific parsing routine for section offsets.
+
+ Plain and simple for now. */
+
+static
+struct section_offsets *
+elf_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets) +
+ sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+/* When handling an ELF file that contains Sun STABS debug info,
+ some of the debug info is relative to the particular chunk of the
+ section that was generated in its individual .o file. E.g.
+ offsets to static variables are relative to the start of the data
+ segment *for that module before linking*. This information is
+ painfully squirreled away in the ELF symbol table as local symbols
+ with wierd names. Go get 'em when needed. */
+
+void
+elfstab_offset_sections (objfile, pst)
+ struct objfile *objfile;
+ struct partial_symtab *pst;
+{
+ char *filename = pst->filename;
+ struct dbx_symfile_info *dbx = (struct dbx_symfile_info *)
+ objfile->sym_stab_info;
+ struct stab_section_info *maybe = dbx->stab_section_info;
+ struct stab_section_info *questionable = 0;
+ int i;
+ char *p;
+
+ /* The ELF symbol info doesn't include path names, so strip the path
+ (if any) from the psymtab filename. */
+ while (0 != (p = strchr (filename, '/')))
+ filename = p+1;
+
+ /* FIXME: This linear search could speed up significantly
+ if it was chained in the right order to match how we search it,
+ and if we unchained when we found a match. */
+ for (; maybe; maybe = maybe->next)
+ {
+ if (filename[0] == maybe->filename[0]
+ && STREQ (filename, maybe->filename))
+ {
+ /* We found a match. But there might be several source files
+ (from different directories) with the same name. */
+ if (0 == maybe->found)
+ break;
+ questionable = maybe; /* Might use it later. */
+ }
+ }
+
+ if (maybe == 0 && questionable != 0)
+ {
+ complain (&stab_info_questionable_complaint, filename);
+ maybe = questionable;
+ }
+
+ if (maybe)
+ {
+ /* Found it! Allocate a new psymtab struct, and fill it in. */
+ maybe->found++;
+ pst->section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets) +
+ sizeof (pst->section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (pst->section_offsets, i) = maybe->sections[i];
+ return;
+ }
+
+ /* We were unable to find any offsets for this file. Complain. */
+ if (dbx->stab_section_info) /* If there *is* any info, */
+ complain (&stab_info_mismatch_complaint, filename);
+}
+
+/* Register that we are able to handle ELF object file formats and DWARF
+ debugging formats.
+
+ Unlike other object file formats, where the debugging information format
+ is implied by the object file format, the ELF object file format and the
+ DWARF debugging information format are two distinct, and potentially
+ separate entities. I.E. it is perfectly possible to have ELF objects
+ with debugging formats other than DWARF. And it is conceivable that the
+ DWARF debugging format might be used with another object file format,
+ like COFF, by simply using COFF's custom section feature.
+
+ GDB, and to a lesser extent BFD, should support the notion of separate
+ object file formats and debugging information formats. For now, we just
+ use "elf" in the same sense as "a.out" or "coff", to imply both the ELF
+ object file format and the DWARF debugging format. */
+
+static struct sym_fns elf_sym_fns =
+{
+ "elf", /* sym_name: name or name prefix of BFD target type */
+ 3, /* sym_namelen: number of significant sym_name chars */
+ elf_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ elf_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ elf_symfile_read, /* sym_read: read a symbol file into symtab */
+ elf_symfile_finish, /* sym_finish: finished with file, cleanup */
+ elf_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_elfread ()
+{
+ add_symtab_fns (&elf_sym_fns);
+}
diff --git a/gnu/usr.bin/gdb/gdb/environ.c b/gnu/usr.bin/gdb/gdb/environ.c
new file mode 100644
index 000000000000..4089212e5add
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/environ.c
@@ -0,0 +1,198 @@
+/* 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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#include "defs.h"
+#include "environ.h"
+#include <string.h>
+#include "defs.h" /* For strsave(). */
+
+
+/* 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 *));
+ }
+
+ memcpy (e->vector, environ, (i + 1) * sizeof (char *));
+
+ while (--i >= 0)
+ {
+ register int len = strlen (e->vector[i]);
+ register char *new = (char *) xmalloc (len + 1);
+ memcpy (new, e->vector[i], 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;
+}
+
+/* Return the value in environment E of variable VAR. */
+
+char *
+get_in_environ (e, var)
+ const struct environ *e;
+ const char *var;
+{
+ register int len = strlen (var);
+ register char **vector = e->vector;
+ register char *s;
+
+ for (; (s = *vector) != NULL; vector++)
+ if (STREQN (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;
+ const char *var;
+ const char *value;
+{
+ register int i;
+ register int len = strlen (var);
+ register char **vector = e->vector;
+ register char *s;
+
+ for (i = 0; (s = vector[i]) != NULL; i++)
+ if (STREQN (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. FIXME: this is a hideous hack and should not be
+ allowed to live. What if we want to change the environment we pass to
+ the program without affecting GDB's behavior? */
+ if (STREQ(var, "PATH")) /* Object file location */
+ {
+ putenv (strsave (s));
+ }
+
+ /* This is a compatibility hack, since GDB 4.10 and older didn't have
+ `set gnutarget'. Eventually it should go away, so that (for example)
+ you can debug objdump's handling of GNUTARGET without affecting GDB's
+ behavior. */
+ if (STREQ (var, "GNUTARGET"))
+ {
+ set_gnutarget (value);
+ }
+ 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) != NULL; vector++)
+ {
+ if (STREQN (s, var, len) && s[len] == '=')
+ {
+ free (s);
+ /* Walk through the vector, shuffling args down by one, including
+ the NULL terminator. Can't use memcpy() here since the regions
+ overlap, and memmove() might not be available. */
+ while ((vector[0] = vector[1]) != NULL)
+ {
+ vector++;
+ }
+ break;
+ }
+ }
+}
diff --git a/gnu/usr.bin/gdb/gdb/environ.h b/gnu/usr.bin/gdb/gdb/environ.h
new file mode 100644
index 000000000000..6c9fd03e3620
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/environ.h
@@ -0,0 +1,58 @@
+/* Header for environment manipulation library.
+ Copyright 1989, 1992 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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (ENVIRON_H)
+#define ENVIRON_H 1
+
+/* 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;
+};
+
+extern struct environ *
+make_environ PARAMS ((void));
+
+extern void
+free_environ PARAMS ((struct environ *));
+
+extern void
+init_environ PARAMS ((struct environ *));
+
+extern char *
+get_in_environ PARAMS ((const struct environ *, const char *));
+
+extern void
+set_in_environ PARAMS ((struct environ *, const char *,
+ const char *));
+
+extern void
+unset_in_environ PARAMS ((struct environ *, char *));
+
+extern char **
+environ_vector PARAMS ((struct environ *));
+
+#endif /* defined (ENVIRON_H) */
diff --git a/gnu/usr.bin/gdb/eval.c b/gnu/usr.bin/gdb/gdb/eval.c
index 60779e688ff4..f641a65f95a4 100644
--- a/gnu/usr.bin/gdb/eval.c
+++ b/gnu/usr.bin/gdb/gdb/eval.c
@@ -1,39 +1,62 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)eval.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
/* Evaluate expressions for GDB.
- Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
-GDB is free software; you can redistribute it and/or modify
+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.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
-#include "param.h"
#include "symtab.h"
+#include "gdbtypes.h"
#include "value.h"
#include "expression.h"
+#include "target.h"
+#include "frame.h"
+#include "language.h" /* For CAST_IS_CONVERSION */
+
+/* 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). */
+};
+
+/* Prototypes for local functions. */
+
+static value
+evaluate_subexp_for_sizeof PARAMS ((struct expression *, int *));
+
+static value
+evaluate_subexp_with_coercion PARAMS ((struct expression *, int *,
+ enum noside));
+
+static value
+evaluate_subexp_for_address PARAMS ((struct expression *, int *,
+ enum noside));
+
+static value
+evaluate_subexp PARAMS ((struct type *, struct expression *, int *,
+ enum noside));
/* Parse the string EXP as a C expression, evaluate it,
@@ -43,12 +66,12 @@ CORE_ADDR
parse_and_eval_address (exp)
char *exp;
{
- struct expression *expr = parse_c_expression (exp);
+ struct expression *expr = parse_expression (exp);
register CORE_ADDR addr;
- register struct cleanup *old_chain
- = make_cleanup (free_current_contents, &expr);
+ register struct cleanup *old_chain =
+ make_cleanup (free_current_contents, &expr);
- addr = (CORE_ADDR) value_as_long (evaluate_expression (expr));
+ addr = value_as_pointer (evaluate_expression (expr));
do_cleanups (old_chain);
return addr;
}
@@ -60,12 +83,12 @@ CORE_ADDR
parse_and_eval_address_1 (expptr)
char **expptr;
{
- struct expression *expr = parse_c_1 (expptr, 0, 0);
+ struct expression *expr = parse_exp_1 (expptr, (struct block *)0, 0);
register CORE_ADDR addr;
- register struct cleanup *old_chain
- = make_cleanup (free_current_contents, &expr);
+ register struct cleanup *old_chain =
+ make_cleanup (free_current_contents, &expr);
- addr = value_as_long (evaluate_expression (expr));
+ addr = value_as_pointer (evaluate_expression (expr));
do_cleanups (old_chain);
return addr;
}
@@ -74,7 +97,7 @@ value
parse_and_eval (exp)
char *exp;
{
- struct expression *expr = parse_c_expression (exp);
+ struct expression *expr = parse_expression (exp);
register value val;
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
@@ -92,7 +115,7 @@ value
parse_to_comma_and_eval (expp)
char **expp;
{
- struct expression *expr = parse_c_1 (expp, 0, 1);
+ struct expression *expr = parse_exp_1 (expp, (struct block *) 0, 1);
register value val;
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
@@ -103,7 +126,7 @@ parse_to_comma_and_eval (expp)
}
/* Evaluate an expression in internal prefix form
- such as is constructed by expread.y.
+ such as is constructed by parse.y.
See expression.h for info on the format of an expression. */
@@ -112,45 +135,12 @@ static value evaluate_subexp_for_address ();
static value evaluate_subexp_for_sizeof ();
static value evaluate_subexp_with_coercion ();
-/* return true if 'var' has an address in inferior's memory. */
-static int
-value_has_lval(var)
- register struct symbol *var;
-{
- switch (SYMBOL_CLASS(var))
- {
- case LOC_STATIC:
- case LOC_LABEL:
- case LOC_ARG:
- case LOC_REF_ARG:
- case LOC_LOCAL:
- case LOC_BLOCK:
- return (1);
- }
- return (0);
-}
-
-/* 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 (0, exp, &pc, EVAL_NORMAL);
+ return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL);
}
/* Evaluate an expression, avoiding all memory references
@@ -161,7 +151,7 @@ evaluate_type (exp)
struct expression *exp;
{
int pc = 0;
- return evaluate_subexp (0, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+ return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
}
static value
@@ -172,9 +162,10 @@ evaluate_subexp (expect_type, exp, pos, noside)
enum noside noside;
{
enum exp_opcode op;
- int tem;
- register int pc, pc2, oldpos;
- register value arg1, arg2, arg3;
+ int tem, tem2, tem3;
+ register int pc, pc2 = 0, oldpos;
+ register value arg1 = NULL, arg2 = NULL, arg3;
+ struct type *type;
int nargs;
value *argvec;
@@ -184,16 +175,21 @@ evaluate_subexp (expect_type, exp, pos, noside)
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);
+ tem = longest_to_int (exp->elts[pc + 2].longconst);
+ (*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
+ arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type,
+ 0,
+ exp->elts[pc + 1].type,
+ &exp->elts[pc + 3].string,
+ expect_type);
+ if (arg1 == NULL)
+ error ("There is no field named %s", &exp->elts[pc + 3].string);
+ return arg1;
case OP_LONG:
(*pos) += 3;
- return value_from_long (exp->elts[pc + 1].type,
- exp->elts[pc + 2].longconst);
+ return value_from_longest (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].longconst);
case OP_DOUBLE:
(*pos) += 3;
@@ -201,12 +197,12 @@ evaluate_subexp (expect_type, exp, pos, noside)
exp->elts[pc + 2].doubleconst);
case OP_VAR_VALUE:
- (*pos) += 2;
+ (*pos) += 3;
if (noside == EVAL_SKIP)
goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
- struct symbol * sym = exp->elts[pc + 1].symbol;
+ struct symbol * sym = exp->elts[pc + 2].symbol;
enum lval_type lv;
switch (SYMBOL_CLASS (sym))
@@ -215,50 +211,81 @@ evaluate_subexp (expect_type, exp, pos, noside)
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);
+ return value_of_variable (exp->elts[pc + 2].symbol,
+ exp->elts[pc + 1].block);
case OP_LAST:
(*pos) += 2;
- return access_value_history ((int) exp->elts[pc + 1].longconst);
+ return
+ access_value_history (longest_to_int (exp->elts[pc + 1].longconst));
case OP_REGISTER:
(*pos) += 2;
- return value_of_register ((int) exp->elts[pc + 1].longconst);
+ return value_of_register (longest_to_int (exp->elts[pc + 1].longconst));
+
+ case OP_BOOL:
+ (*pos) += 2;
+ return value_from_longest (builtin_type_chill_bool,
+ 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));
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_string (&exp->elts[pc + 2].string, tem);
+
+ case OP_BITSTRING:
+ error ("support for OP_BITSTRING unimplemented");
+ break;
+
+ case OP_ARRAY:
+ (*pos) += 3;
+ tem2 = longest_to_int (exp->elts[pc + 1].longconst);
+ tem3 = longest_to_int (exp->elts[pc + 2].longconst);
+ nargs = tem3 - tem2 + 1;
+ argvec = (value *) alloca (sizeof (value) * nargs);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ /* Ensure that array expressions are coerced into pointer objects. */
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ }
if (noside == EVAL_SKIP)
goto nosideret;
- return value_string (&exp->elts[pc + 1].string, tem);
+ return (value_array (tem2, tem3, argvec));
+ break;
case TERNOP_COND:
/* Skip third and second args to evaluate the first one. */
- arg1 = evaluate_subexp (0, exp, pos, noside);
- if (value_zerop (arg1))
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (value_logical_not (arg1))
{
- evaluate_subexp (0, exp, pos, EVAL_SKIP);
- return evaluate_subexp (0, exp, pos, noside);
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
}
else
{
- arg2 = evaluate_subexp (0, exp, pos, noside);
- evaluate_subexp (0, exp, pos, EVAL_SKIP);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
return arg2;
}
@@ -268,9 +295,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
{
int fnptr;
- int tem2;
- nargs = (int) exp->elts[pc + 1].longconst + 1;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1;
/* First, evaluate the structure into arg2 */
pc2 = (*pos)++;
@@ -283,7 +309,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
- arg2 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
}
/* If the function is a virtual function, then the
@@ -292,42 +318,37 @@ evaluate_subexp (expect_type, exp, pos, noside)
it is just along for the ride: call the function
directly. */
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
- fnptr = (int) value_as_long (arg1);
- if (fnptr < 128)
+ fnptr = longest_to_int (value_as_long (arg1));
+
+ if (METHOD_PTR_IS_VIRTUAL(fnptr))
{
+ int fnoffset = METHOD_PTR_TO_VOFFSET(fnptr);
struct type *basetype;
+ struct type *domain_type =
+ TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
int i, j;
basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
- basetype = TYPE_VPTR_BASETYPE (basetype);
+ if (domain_type != basetype)
+ arg2 = value_cast(lookup_pointer_type (domain_type), arg2);
+ basetype = TYPE_VPTR_BASETYPE (domain_type);
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)
+ if (TYPE_FN_FIELD_VOFFSET (f, j) == fnoffset)
{
- 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;
+ value temp = value_ind (arg2);
+ arg1 = value_virtual_fn_field (&temp, f, j, domain_type, 0);
+ arg2 = value_addr (temp);
goto got_it;
}
}
if (i < 0)
- error ("virtual function at index %d not found", fnptr);
+ error ("virtual function at index %d not found", fnoffset);
}
else
{
@@ -343,30 +364,46 @@ evaluate_subexp (expect_type, exp, pos, noside)
/* Hair for method invocations */
int tem2;
- nargs = (int) exp->elts[pc + 1].longconst + 1;
+ nargs = longest_to_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);
+ tem2 = longest_to_int (exp->elts[pc2 + 1].longconst);
+ *pos += 3 + BYTES_TO_EXP_ELEM (tem2 + 1);
if (noside == EVAL_SKIP)
goto nosideret;
if (op == STRUCTOP_STRUCT)
{
+ /* If v is a variable in a register, and the user types
+ v.method (), this will produce an error, because v has
+ no address.
+
+ A possible way around this would be to allocate a
+ copy of the variable on the stack, copy in the
+ contents, call the function, and copy out the
+ contents. I.e. convert this from call by reference
+ to call by copy-return (or whatever it's called).
+ However, this does not work because it is not the
+ same: the method being called could stash a copy of
+ the address, and then future uses through that address
+ (after the method returns) would be expected to
+ use the variable itself, not some copy of it. */
arg2 = evaluate_subexp_for_address (exp, pos, noside);
}
else
{
- arg2 = evaluate_subexp (0, exp, pos, noside);
+ 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;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
tem = 0;
}
+ /* Allocate arg vector, including space for the function to be
+ called in argvec[0] and a terminating NULL */
argvec = (value *) alloca (sizeof (value) * (nargs + 2));
for (; tem <= nargs; tem++)
/* Ensure that array expressions are coerced into pointer objects. */
@@ -378,13 +415,17 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
{
int static_memfuncp;
+ value temp = arg2;
argvec[1] = arg2;
argvec[0] =
- value_struct_elt (arg2, argvec+1, &exp->elts[pc2 + 1].string,
+ value_struct_elt (&temp, argvec+1, &exp->elts[pc2 + 2].string,
&static_memfuncp,
op == STRUCTOP_STRUCT
? "structure" : "structure pointer");
+ arg2 = value_from_longest (lookup_pointer_type (VALUE_TYPE (temp)),
+ VALUE_ADDRESS (temp)+VALUE_OFFSET (temp));
+ argvec[1] = arg2;
if (static_memfuncp)
{
argvec[1] = argvec[0];
@@ -417,99 +458,92 @@ evaluate_subexp (expect_type, exp, pos, noside)
else
error ("Expression of type other than \"Function returning ...\" used as function");
}
- return call_function (argvec[0], nargs, argvec + 1);
+ return call_function_by_hand (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));
-
- /* Try to convert "foo.bar" into "(&foo)->bar" so we won't copy
- * the entire contents of a large struct just to extract one
- * value from it. */
- if (noside == EVAL_NORMAL && exp->elts[*pos].opcode == OP_VAR_VALUE
- && value_has_lval(exp->elts[*pos + 1].symbol))
- arg1 = evaluate_subexp_for_address(exp, pos, noside);
- else
- arg1 = evaluate_subexp (0, exp, pos, noside);
-
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ 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 + 2].string,
+ 0),
+ lval_memory);
+ else
{
- register struct type *type = VALUE_TYPE (arg1);
- if (TYPE_CODE (type) == TYPE_CODE_PTR)
- type = TYPE_TARGET_TYPE (type);
- return value_zero (lookup_struct_elt_type (type,
- &exp->elts[pc + 1].string),
- lval_memory);
+ value temp = arg1;
+ return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 2].string,
+ (int *) 0, "structure");
}
- else
- return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 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 (0, exp, pos, noside);
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ 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),
+ return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
+ &exp->elts[pc + 2].string,
+ 0),
lval_memory);
else
- return value_struct_elt (arg1, 0, &exp->elts[pc + 1].string, 0,
- "structure pointer");
+ {
+ value temp = arg1;
+ return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 2].string,
+ (int *) 0, "structure pointer");
+ }
case STRUCTOP_MEMBER:
arg1 = evaluate_subexp_for_address (exp, pos, noside);
- arg2 = evaluate_subexp (0, exp, pos, noside);
+ goto handle_pointer_to_member;
+ case STRUCTOP_MPTR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ handle_pointer_to_member:
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
+ if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR)
+ goto bad_pointer_to_member;
+ type = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
+ if (TYPE_CODE (type) == TYPE_CODE_METHOD)
+ error ("not implemented: pointer-to-method in pointer-to-member construct");
+ if (TYPE_CODE (type) != TYPE_CODE_MEMBER)
+ goto bad_pointer_to_member;
/* 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))));
+ arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
+ arg1);
+ arg3 = value_from_longest (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+ value_as_long (arg1) + value_as_long (arg2));
return value_ind (arg3);
+ bad_pointer_to_member:
+ error("non-pointer-to-member value used in pointer-to-member construct");
- case STRUCTOP_MPTR:
- arg1 = evaluate_subexp (0, exp, pos, noside);
- arg2 = evaluate_subexp (0, exp, pos, noside);
+ case BINOP_CONCAT:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (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);
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ else
+ return value_concat (arg1, arg2);
case BINOP_ASSIGN:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ 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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
return value_assign (arg1, arg2);
case BINOP_ASSIGN_MODIFY:
(*pos) += 2;
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ 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;
@@ -530,7 +564,7 @@ evaluate_subexp (expect_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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
return value_add (arg1, arg2);
@@ -540,27 +574,28 @@ evaluate_subexp (expect_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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
return value_sub (arg1, arg2);
case BINOP_MUL:
case BINOP_DIV:
case BINOP_REM:
+ case BINOP_MOD:
case BINOP_LSH:
case BINOP_RSH:
- case BINOP_LOGAND:
- case BINOP_LOGIOR:
- case BINOP_LOGXOR:
- arg1 = evaluate_subexp (0, exp, pos, noside);
- arg2 = evaluate_subexp (0, exp, pos, noside);
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ 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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
if (noside == EVAL_AVOID_SIDE_EFFECTS
- && op == BINOP_DIV)
+ && (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD))
return value_zero (VALUE_TYPE (arg1), not_lval);
else
return value_binop (arg1, arg2, op);
@@ -571,175 +606,236 @@ evaluate_subexp (expect_type, 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 the user attempts to subscript something that has no target
+ type (like a plain int variable for example), then report this
+ as an error. */
+
+ type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1));
+ if (type)
+ return value_zero (type, VALUE_LVAL (arg1));
+ else
+ error ("cannot subscript something of type `%s'",
+ TYPE_NAME (VALUE_TYPE (arg1)));
+ }
if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
return value_subscript (arg1, arg2);
- case BINOP_AND:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ case MULTI_SUBSCRIPT:
+ (*pos) += 2;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ while (nargs-- > 0)
+ {
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ /* FIXME: EVAL_SKIP handling may not be correct. */
+ if (noside == EVAL_SKIP)
+ {
+ if (nargs > 0)
+ {
+ continue;
+ }
+ else
+ {
+ goto nosideret;
+ }
+ }
+ /* FIXME: EVAL_AVOID_SIDE_EFFECTS handling may not be correct. */
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the user attempts to subscript something that has no target
+ type (like a plain int variable for example), then report this
+ as an error. */
+
+ type = TYPE_TARGET_TYPE (VALUE_TYPE (arg1));
+ if (type != NULL)
+ {
+ arg1 = value_zero (type, VALUE_LVAL (arg1));
+ noside = EVAL_SKIP;
+ continue;
+ }
+ else
+ {
+ error ("cannot subscript something of type `%s'",
+ TYPE_NAME (VALUE_TYPE (arg1)));
+ }
+ }
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ arg1 = value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ arg1 = value_subscript (arg1, arg2);
+ }
+ }
+ return (arg1);
+
+ case BINOP_LOGICAL_AND:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP)
{
- arg2 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
goto nosideret;
}
oldpos = *pos;
- arg2 = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
*pos = oldpos;
if (binop_user_defined_p (op, arg1, arg2))
{
- arg2 = evaluate_subexp (0, exp, pos, noside);
- return value_x_binop (arg1, arg2, op, 0);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
- tem = value_zerop (arg1);
- arg2 = evaluate_subexp (0, exp, pos,
+ tem = value_logical_not (arg1);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
(tem ? EVAL_SKIP : noside));
- return value_from_long (builtin_type_int,
- (LONGEST) (!tem && !value_zerop (arg2)));
+ return value_from_longest (builtin_type_int,
+ (LONGEST) (!tem && !value_logical_not (arg2)));
}
- case BINOP_OR:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ case BINOP_LOGICAL_OR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP)
{
- arg2 = evaluate_subexp (0, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
goto nosideret;
}
oldpos = *pos;
- arg2 = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
*pos = oldpos;
if (binop_user_defined_p (op, arg1, arg2))
{
- arg2 = evaluate_subexp (0, exp, pos, noside);
- return value_x_binop (arg1, arg2, op, 0);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
- tem = value_zerop (arg1);
- arg2 = evaluate_subexp (0, exp, pos,
+ tem = value_logical_not (arg1);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
(!tem ? EVAL_SKIP : noside));
- return value_from_long (builtin_type_int,
- (LONGEST) (!tem || !value_zerop (arg2)));
+ return value_from_longest (builtin_type_int,
+ (LONGEST) (!tem || !value_logical_not (arg2)));
}
case BINOP_EQUAL:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ 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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_equal (arg1, arg2);
- return value_from_long (builtin_type_int, (LONGEST) tem);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_NOTEQUAL:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ 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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_equal (arg1, arg2);
- return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ return value_from_longest (builtin_type_int, (LONGEST) ! tem);
}
case BINOP_LESS:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ 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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_less (arg1, arg2);
- return value_from_long (builtin_type_int, (LONGEST) tem);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_GTR:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ 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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_less (arg2, arg1);
- return value_from_long (builtin_type_int, (LONGEST) tem);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_GEQ:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ 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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
- tem = value_less (arg1, arg2);
- return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ tem = value_less (arg2, arg1) || value_equal (arg1, arg2);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_LEQ:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ 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);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
- tem = value_less (arg2, arg1);
- return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ tem = value_less (arg1, arg2) || value_equal (arg1, arg2);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_REPEAT:
- arg1 = evaluate_subexp (0, exp, pos, noside);
- arg2 = evaluate_subexp (0, exp, pos, noside);
+ 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));
+ longest_to_int (value_as_long (arg2)));
else
- return value_repeat (arg1, (int) value_as_long (arg2));
+ return value_repeat (arg1, longest_to_int (value_as_long (arg2)));
case BINOP_COMMA:
- evaluate_subexp (0, exp, pos, noside);
- return evaluate_subexp (0, exp, pos, noside);
+ evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
case UNOP_NEG:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
if (unop_user_defined_p (op, arg1))
@@ -747,24 +843,27 @@ evaluate_subexp (expect_type, exp, pos, noside)
else
return value_neg (arg1);
- case UNOP_LOGNOT:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ case UNOP_COMPLEMENT:
+ /* C++: check for and handle destructor names. */
+ op = exp->elts[*pos].opcode;
+
+ 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);
+ if (unop_user_defined_p (UNOP_COMPLEMENT, arg1))
+ return value_x_unop (arg1, UNOP_COMPLEMENT);
else
- return value_lognot (arg1);
+ return value_complement (arg1);
- case UNOP_ZEROP:
- arg1 = evaluate_subexp (0, exp, pos, noside);
+ case UNOP_LOGICAL_NOT:
+ 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));
+ return value_from_longest (builtin_type_int,
+ (LONGEST) value_logical_not (arg1));
case UNOP_IND:
if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
@@ -798,33 +897,20 @@ evaluate_subexp (expect_type, exp, pos, noside)
{
if (op == OP_SCOPE)
{
- char *name = &exp->elts[pc+3].string;
- int tem = strlen (name);
- (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
+ int temm = longest_to_int (exp->elts[pc+3].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (temm + 1);
}
else
evaluate_subexp (expect_type, exp, pos, EVAL_SKIP);
goto nosideret;
}
- if (op == OP_SCOPE)
- {
- char *name = &exp->elts[pc+3].string;
- int tem = strlen (name);
- struct type *domain = exp->elts[pc+2].type;
- (*pos) += 2 + (tem + 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);
+ return evaluate_subexp_for_address (exp, pos, noside);
case UNOP_SIZEOF:
if (noside == EVAL_SKIP)
{
- evaluate_subexp (0, exp, pos, EVAL_SKIP);
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
goto nosideret;
}
return evaluate_subexp_for_sizeof (exp, pos);
@@ -844,8 +930,8 @@ evaluate_subexp (expect_type, exp, pos, noside)
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (exp->elts[pc + 1].type, lval_memory);
else
- return value_at (exp->elts[pc + 1].type,
- (CORE_ADDR) value_as_long (arg1));
+ return value_at_lazy (exp->elts[pc + 1].type,
+ value_as_pointer (arg1));
case UNOP_PREINCREMENT:
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
@@ -857,7 +943,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
- arg2 = value_add (arg1, value_from_long (builtin_type_char,
+ arg2 = value_add (arg1, value_from_longest (builtin_type_char,
(LONGEST) 1));
return value_assign (arg1, arg2);
}
@@ -872,7 +958,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
- arg2 = value_sub (arg1, value_from_long (builtin_type_char,
+ arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
(LONGEST) 1));
return value_assign (arg1, arg2);
}
@@ -887,7 +973,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
- arg2 = value_add (arg1, value_from_long (builtin_type_char,
+ arg2 = value_add (arg1, value_from_longest (builtin_type_char,
(LONGEST) 1));
value_assign (arg1, arg2);
return arg1;
@@ -903,7 +989,7 @@ evaluate_subexp (expect_type, exp, pos, noside)
}
else
{
- arg2 = value_sub (arg1, value_from_long (builtin_type_char,
+ arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
(LONGEST) 1));
value_assign (arg1, arg2);
return arg1;
@@ -913,12 +999,26 @@ evaluate_subexp (expect_type, exp, pos, noside)
(*pos) += 1;
return value_of_this (1);
+ case OP_TYPE:
+ error ("Attempt to use a type name as an expression");
+
default:
- error ("internal error: I do not know how to evaluate what you gave me");
+ /* Removing this case and compiling with gcc -Wall reveals that
+ a lot of cases are hitting this case. Some of these should
+ probably be removed from expression.h (e.g. do we need a BINOP_SCOPE
+ and an OP_SCOPE?); others are legitimate expressions which are
+ (apparently) not fully implemented.
+
+ If there are any cases landing here which mean a user error,
+ then they should be separate cases, with more descriptive
+ error messages. */
+
+ error ("\
+GDB does not (yet) know how to evaluated that kind of expression");
}
nosideret:
- return value_from_long (builtin_type_long, (LONGEST) 1);
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
}
/* Evaluate a subexpression of EXP, at index *POS,
@@ -936,6 +1036,7 @@ evaluate_subexp_for_address (exp, pos, noside)
{
enum exp_opcode op;
register int pc;
+ struct symbol *var;
pc = (*pos);
op = exp->elts[pc].opcode;
@@ -944,21 +1045,27 @@ evaluate_subexp_for_address (exp, pos, noside)
{
case UNOP_IND:
(*pos)++;
- return evaluate_subexp (0, exp, pos, noside);
+ 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 (0, exp, pos, noside));
+ evaluate_subexp (NULL_TYPE, exp, pos, noside));
case OP_VAR_VALUE:
- (*pos) += 3;
+ var = exp->elts[pc + 2].symbol;
+
+ /* C++: The "address" of a reference should yield the address
+ * of the object pointed to. Let value_addr() deal with it. */
+ if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_REF)
+ goto default_case;
+
+ (*pos) += 4;
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);
+ lookup_pointer_type (SYMBOL_TYPE (var));
+ enum address_class sym_class = SYMBOL_CLASS (var);
if (sym_class == LOC_CONST
|| sym_class == LOC_CONST_BYTES
@@ -970,26 +1077,38 @@ evaluate_subexp_for_address (exp, pos, noside)
value_zero (type, not_lval);
}
else
- return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
+ return
+ locate_var_value
+ (var,
+ block_innermost_frame (exp->elts[pc + 1].block));
default:
+ default_case:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
- value x = evaluate_subexp (0, exp, pos, noside);
+ value x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (VALUE_LVAL (x) == lval_memory)
- return value_zero (TYPE_POINTER_TYPE (VALUE_TYPE (x)),
+ return value_zero (lookup_pointer_type (VALUE_TYPE (x)),
not_lval);
else
error ("Attempt to take address of non-lval");
}
- return value_addr (evaluate_subexp (0, exp, pos, noside));
+ 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. */
+ 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 (perhaps obsolete now that we have
+ VALUE_LAZY).
+
+ Note that we currently only do the coercion for C expressions, where
+ arrays are zero based and the coercion is correct. For other languages,
+ with nonzero based arrays, coercion loses. Use CAST_IS_CONVERSION
+ to decide if coercion is appropriate.
+
+ */
static value
evaluate_subexp_with_coercion (exp, pos, noside)
@@ -1000,6 +1119,7 @@ evaluate_subexp_with_coercion (exp, pos, noside)
register enum exp_opcode op;
register int pc;
register value val;
+ struct symbol *var;
pc = (*pos);
op = exp->elts[pc].opcode;
@@ -1007,16 +1127,22 @@ evaluate_subexp_with_coercion (exp, pos, noside)
switch (op)
{
case OP_VAR_VALUE:
- if (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 1].symbol)) == TYPE_CODE_ARRAY)
+ var = exp->elts[pc + 2].symbol;
+ if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_ARRAY
+ && CAST_IS_CONVERSION)
{
- (*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))),
+ (*pos) += 4;
+ val =
+ locate_var_value
+ (var, block_innermost_frame (exp->elts[pc + 1].block));
+ return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (var))),
val);
}
- }
+ /* FALLTHROUGH */
- return evaluate_subexp (0, exp, pos, noside);
+ default:
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
}
/* Evaluate a subexpression of EXP, at index *POS,
@@ -1043,23 +1169,45 @@ evaluate_subexp_for_sizeof (exp, pos)
create a value unnecessarily. */
case UNOP_IND:
(*pos)++;
- val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- return value_from_long (builtin_type_int, (LONGEST)
+ val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ return value_from_longest (builtin_type_int, (LONGEST)
TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
case UNOP_MEMVAL:
(*pos) += 3;
- return value_from_long (builtin_type_int,
+ return value_from_longest (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)));
+ (*pos) += 4;
+ return
+ value_from_longest
+ (builtin_type_int,
+ (LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 2].symbol)));
default:
- val = evaluate_subexp (0, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- return value_from_long (builtin_type_int,
+ val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ return value_from_longest (builtin_type_int,
(LONGEST) TYPE_LENGTH (VALUE_TYPE (val)));
}
}
+
+/* Parse a type expression in the string [P..P+LENGTH). */
+
+struct type *
+parse_and_eval_type (p, length)
+ char *p;
+ int length;
+{
+ char *tmp = (char *)alloca (length + 4);
+ struct expression *expr;
+ tmp[0] = '(';
+ memcpy (tmp+1, p, length);
+ tmp[length+1] = ')';
+ tmp[length+2] = '0';
+ tmp[length+3] = '\0';
+ expr = parse_expression (tmp);
+ if (expr->elts[0].opcode != UNOP_CAST)
+ error ("Internal error in eval_type.");
+ return expr->elts[1].type;
+}
diff --git a/gnu/usr.bin/gdb/gdb/exec.c b/gnu/usr.bin/gdb/gdb/exec.c
new file mode 100644
index 000000000000..f66a33c2cdc5
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/exec.c
@@ -0,0 +1,489 @@
+/* Work with executable files, for GDB.
+ Copyright 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcmd.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "gdbcore.h"
+
+#include <ctype.h>
+#include <sys/stat.h>
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* Prototypes for local functions */
+
+static void
+add_to_section_table PARAMS ((bfd *, sec_ptr, PTR));
+
+static void
+exec_close PARAMS ((int));
+
+static void
+file_command PARAMS ((char *, int));
+
+static void
+set_section_command PARAMS ((char *, int));
+
+static void
+exec_files_info PARAMS ((struct target_ops *));
+
+extern int info_verbose;
+
+/* The Binary File Descriptor handle for the executable file. */
+
+bfd *exec_bfd = NULL;
+
+/* Whether to open exec and core files read-only or read-write. */
+
+int write_files = 0;
+
+/* Text start and end addresses (KLUDGE) if needed */
+
+#ifdef NEED_TEXT_START_END
+CORE_ADDR text_start = 0;
+CORE_ADDR text_end = 0;
+#endif
+
+/* Forward decl */
+
+extern struct target_ops exec_ops;
+
+/* ARGSUSED */
+static void
+exec_close (quitting)
+ int quitting;
+{
+ if (exec_bfd) {
+ char *name = bfd_get_filename (exec_bfd);
+ bfd_close (exec_bfd);
+ free (name);
+ exec_bfd = NULL;
+ }
+ if (exec_ops.to_sections) {
+ free ((PTR)exec_ops.to_sections);
+ exec_ops.to_sections = NULL;
+ exec_ops.to_sections_end = NULL;
+ }
+}
+
+/* Process the first arg in ARGS as the new exec file.
+
+ Note that we have to explicitly ignore additional args, since we can
+ be called from file_command(), which also calls symbol_file_command()
+ which can take multiple args. */
+
+void
+exec_file_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ char *filename;
+
+ target_preopen (from_tty);
+
+ /* Remove any previous exec file. */
+ unpush_target (&exec_ops);
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (args)
+ {
+ char *scratch_pathname;
+ int scratch_chan;
+
+ /* Scan through the args and pick up the first non option arg
+ as the filename. */
+
+ if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ make_cleanup (freeargv, (char *) argv);
+
+ for (; (*argv != NULL) && (**argv == '-'); argv++) {;}
+ if (*argv == NULL)
+ {
+ error ("no exec file name was specified");
+ }
+
+ filename = tilde_expand (*argv);
+ make_cleanup (free, filename);
+
+ scratch_chan = openp (getenv ("PATH"), 1, filename,
+ write_files? O_RDWR|O_BINARY: O_RDONLY|O_BINARY, 0,
+ &scratch_pathname);
+ if (scratch_chan < 0)
+ perror_with_name (filename);
+
+ exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, 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 (build_section_table (exec_bfd, &exec_ops.to_sections,
+ &exec_ops.to_sections_end))
+ error ("Can't find the file sections in `%s': %s",
+ exec_bfd->filename, bfd_errmsg (bfd_error));
+
+#ifdef NEED_TEXT_START_END
+
+ /* text_end is sometimes used for where to put call dummies. A
+ few ports use these for other purposes too. */
+
+ {
+ struct section_table *p;
+
+ /* Set text_start to the lowest address of the start of any
+ readonly code section and set text_end to the highest
+ address of the end of any readonly code section. */
+
+ text_start = ~(CORE_ADDR)0;
+ text_end = (CORE_ADDR)0;
+ for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++)
+ if (bfd_get_section_flags (p->bfd, p->sec_ptr)
+ & (SEC_CODE | SEC_READONLY))
+ {
+ if (text_start > p->addr)
+ text_start = p->addr;
+ if (text_end < p->endaddr)
+ text_end = p->endaddr;
+ }
+ }
+#endif
+
+ 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? */
+
+static 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);
+}
+
+
+/* Locate all mappable sections of a BFD file.
+ table_pp_char is a char * to get it through bfd_map_over_sections;
+ we cast it back to its proper type. */
+
+static void
+add_to_section_table (abfd, asect, table_pp_char)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR table_pp_char;
+{
+ struct section_table **table_pp = (struct section_table **)table_pp_char;
+ 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;
+ if (0 == bfd_section_size (abfd, asect))
+ return;
+ (*table_pp)->bfd = abfd;
+ (*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)++;
+}
+
+/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
+ Returns 0 if OK, 1 on error. */
+
+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 (*start)
+ free ((PTR)*start);
+ *start = (struct section_table *) xmalloc (count * sizeof (**start));
+ *end = *start;
+ bfd_map_over_sections (some_bfd, add_to_section_table, (char *)end);
+ if (*end > *start + count)
+ abort();
+ /* We could realloc the table, but it probably loses for most files. */
+ return 0;
+}
+
+/* Read or write the exec file.
+
+ Args are address within a BFD 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, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ boolean res;
+ struct section_table *p;
+ CORE_ADDR nextsectaddr, memend;
+ boolean (*xfer_fn) PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));
+
+ if (len <= 0)
+ abort();
+
+ memend = memaddr + len;
+ xfer_fn = write? bfd_set_section_contents: bfd_get_section_contents;
+ nextsectaddr = memend;
+
+ for (p = target->to_sections; p < target->to_sections_end; p++)
+ {
+ if (p->addr <= memaddr)
+ if (p->endaddr >= memend)
+ {
+ /* Entire transfer is within this section. */
+ res = xfer_fn (p->bfd, 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 (p->bfd, 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 */
+}
+
+#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 */
+
+void
+print_section_info (t, abfd)
+ struct target_ops *t;
+ bfd *abfd;
+{
+ struct section_table *p;
+
+ printf_filtered ("\t`%s', ", bfd_get_filename(abfd));
+ wrap_here (" ");
+ printf_filtered ("file type %s.\n", bfd_get_target(abfd));
+ printf_filtered ("\tEntry point: %s\n",
+ local_hex_string ((unsigned long) bfd_get_start_address (exec_bfd)));
+ for (p = t->to_sections; p < t->to_sections_end; p++) {
+ printf_filtered ("\t%s", local_hex_string_custom ((unsigned long) p->addr, "08l"));
+ printf_filtered (" - %s", local_hex_string_custom ((unsigned long) p->endaddr, "08l"));
+ if (info_verbose)
+ printf_filtered (" @ %s",
+ local_hex_string_custom ((unsigned long) p->sec_ptr->filepos, "08l"));
+ printf_filtered (" is %s", bfd_section_name (p->bfd, p->sec_ptr));
+ if (p->bfd != abfd) {
+ printf_filtered (" in %s", bfd_get_filename (p->bfd));
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+exec_files_info (t)
+ struct target_ops *t;
+{
+ print_section_info (t, exec_bfd);
+}
+
+static void
+set_section_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct section_table *p;
+ char *secname;
+ unsigned seclen;
+ unsigned long secaddr;
+ char secprint[100];
+ long offset;
+
+ if (args == 0)
+ error ("Must specify section name and its virtual address");
+
+ /* Parse out section name */
+ for (secname = args; !isspace(*args); args++) ;
+ seclen = args - secname;
+
+ /* Parse out new virtual address */
+ secaddr = parse_and_eval_address (args);
+
+ for (p = exec_ops.to_sections; p < exec_ops.to_sections_end; p++) {
+ if (!strncmp (secname, bfd_section_name (exec_bfd, p->sec_ptr), seclen)
+ && bfd_section_name (exec_bfd, p->sec_ptr)[seclen] == '\0') {
+ offset = secaddr - p->addr;
+ p->addr += offset;
+ p->endaddr += offset;
+ if (from_tty)
+ exec_files_info(&exec_ops);
+ return;
+ }
+ }
+ if (seclen >= sizeof (secprint))
+ seclen = sizeof (secprint) - 1;
+ strncpy (secprint, secname, seclen);
+ secprint[seclen] = '\0';
+ error ("Section %s not found", secprint);
+}
+
+/* If mourn is being called in all the right places, this could be say
+ `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */
+
+static int
+ignore (addr, contents)
+ CORE_ADDR addr;
+ char *contents;
+{
+ return 0;
+}
+
+struct target_ops exec_ops = {
+ "exec", "Local exec file",
+ "Use an executable file as a target.\n\
+Specify the filename of the executable file.",
+ exec_file_command, exec_close, /* open, close */
+ find_default_attach, 0, 0, 0, /* attach, detach, resume, wait, */
+ 0, 0, /* fetch_registers, store_registers, */
+ 0, /* prepare_to_store, */
+ xfer_memory, exec_files_info,
+ ignore, ignore, /* insert_breakpoint, remove_breakpoint, */
+ 0, 0, 0, 0, 0, /* terminal stuff */
+ 0, 0, /* kill, load */
+ 0, /* lookup sym */
+ find_default_create_inferior,
+ 0, /* mourn_inferior */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ file_stratum, 0, /* next */
+ 0, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */
+ 0, 0, /* section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_exec()
+{
+ struct cmd_list_element *c;
+
+ c = add_cmd ("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.", &cmdlist);
+ c->completer = filename_completer;
+
+ c = add_cmd ("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.", &cmdlist);
+ c->completer = filename_completer;
+
+ add_com ("section", class_files, set_section_command,
+ "Change the base address of section SECTION of the exec file to ADDR.\n\
+This can be used if the exec file does not contain section addresses,\n\
+(such as in the a.out format), or when the addresses specified in the\n\
+file itself are wrong. Each section must be changed separately. The\n\
+``info files'' command lists all the sections and their addresses.");
+
+ add_show_from_set
+ (add_set_cmd ("write", class_support, var_boolean, (char *)&write_files,
+ "Set writing into executable and core files.",
+ &setlist),
+ &showlist);
+
+ add_target (&exec_ops);
+}
diff --git a/gnu/usr.bin/gdb/gdb/expprint.c b/gnu/usr.bin/gdb/gdb/expprint.c
new file mode 100644
index 000000000000..607b3df7037a
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/expprint.c
@@ -0,0 +1,623 @@
+/* Print in infix form a struct expression.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "language.h"
+#include "parser-defs.h"
+
+/* Prototypes for local functions */
+
+static void
+print_subexp PARAMS ((struct expression *, int *, FILE *, enum precedence));
+
+static void
+print_simple_m2_func PARAMS ((char *, struct expression *, int *, FILE *));
+
+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 const struct op_print *op_print_tab;
+ register int pc;
+ unsigned nargs;
+ register char *op_str;
+ int assign_modify = 0;
+ enum exp_opcode opcode;
+ enum precedence myprec = PREC_NULL;
+ /* Set to 1 for a right-associative operator. */
+ int assoc = 0;
+ value val;
+ char *tempstr = NULL;
+
+ op_print_tab = exp->language_defn->la_op_print_tab;
+ pc = (*pos)++;
+ opcode = exp->elts[pc].opcode;
+ switch (opcode)
+ {
+ /* Common ops */
+
+ case OP_SCOPE:
+ myprec = PREC_PREFIX;
+ assoc = 0;
+ fputs_filtered (type_name_no_tag (exp->elts[pc + 1].type), stream);
+ fputs_filtered ("::", stream);
+ nargs = longest_to_int (exp->elts[pc + 2].longconst);
+ (*pos) += 4 + BYTES_TO_EXP_ELEM (nargs + 1);
+ fputs_filtered (&exp->elts[pc + 3].string, stream);
+ return;
+
+ case OP_LONG:
+ (*pos) += 3;
+ value_print (value_from_longest (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:
+ {
+ struct block *b;
+ (*pos) += 3;
+ b = exp->elts[pc + 1].block;
+ if (b != NULL
+ && BLOCK_FUNCTION (b) != NULL
+ && SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)) != NULL)
+ {
+ fputs_filtered (SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)), stream);
+ fputs_filtered ("::", stream);
+ }
+ fputs_filtered (SYMBOL_SOURCE_NAME (exp->elts[pc + 2].symbol), stream);
+ }
+ return;
+
+ case OP_LAST:
+ (*pos) += 2;
+ fprintf_filtered (stream, "$%d",
+ longest_to_int (exp->elts[pc + 1].longconst));
+ return;
+
+ case OP_REGISTER:
+ (*pos) += 2;
+ fprintf_filtered (stream, "$%s",
+ reg_names[longest_to_int (exp->elts[pc + 1].longconst)]);
+ return;
+
+ case OP_BOOL:
+ (*pos) += 2;
+ fprintf_filtered (stream, "%s",
+ longest_to_int (exp->elts[pc + 1].longconst)
+ ? "TRUE" : "FALSE");
+ return;
+
+ case OP_INTERNALVAR:
+ (*pos) += 2;
+ fprintf_filtered (stream, "$%s",
+ internalvar_name (exp->elts[pc + 1].internalvar));
+ return;
+
+ case OP_FUNCALL:
+ (*pos) += 2;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered (" (", stream);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ if (tem != 0)
+ fputs_filtered (", ", stream);
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ fputs_filtered (")", stream);
+ return;
+
+ case OP_STRING:
+ nargs = longest_to_int (exp -> elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
+ /* LA_PRINT_STRING will print using the current repeat count threshold.
+ If necessary, we can temporarily set it to zero, or pass it as an
+ additional parameter to LA_PRINT_STRING. -fnf */
+ LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 0);
+ return;
+
+ case OP_BITSTRING:
+ error ("support for OP_BITSTRING unimplemented");
+ break;
+
+ case OP_ARRAY:
+ (*pos) += 3;
+ nargs = longest_to_int (exp->elts[pc + 2].longconst);
+ nargs -= longest_to_int (exp->elts[pc + 1].longconst);
+ nargs++;
+ tem = 0;
+ if (exp->elts[pc + 4].opcode == OP_LONG
+ && exp->elts[pc + 5].type == builtin_type_char
+ && exp->language_defn->la_language == language_c)
+ {
+ /* Attempt to print C character arrays using string syntax.
+ Walk through the args, picking up one character from each
+ of the OP_LONG expression elements. If any array element
+ does not match our expection of what we should find for
+ a simple string, revert back to array printing. Note that
+ the last expression element is an explicit null terminator
+ byte, which doesn't get printed. */
+ tempstr = alloca (nargs);
+ pc += 4;
+ while (tem < nargs)
+ {
+ if (exp->elts[pc].opcode != OP_LONG
+ || exp->elts[pc + 1].type != builtin_type_char)
+ {
+ /* Not a simple array of char, use regular array printing. */
+ tem = 0;
+ break;
+ }
+ else
+ {
+ tempstr[tem++] =
+ longest_to_int (exp->elts[pc + 2].longconst);
+ pc += 4;
+ }
+ }
+ }
+ if (tem > 0)
+ {
+ LA_PRINT_STRING (stream, tempstr, nargs - 1, 0);
+ (*pos) = pc;
+ }
+ else
+ {
+ fputs_filtered (" {", stream);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ if (tem != 0)
+ {
+ fputs_filtered (", ", stream);
+ }
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ fputs_filtered ("}", stream);
+ }
+ return;
+
+ case TERNOP_COND:
+ if ((int) prec > (int) PREC_COMMA)
+ fputs_filtered ("(", 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);
+ fputs_filtered (" ? ", stream);
+ print_subexp (exp, pos, stream, PREC_HYPER);
+ fputs_filtered (" : ", stream);
+ print_subexp (exp, pos, stream, PREC_HYPER);
+ if ((int) prec > (int) PREC_COMMA)
+ fputs_filtered (")", stream);
+ return;
+
+ case STRUCTOP_STRUCT:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered (".", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ return;
+
+ /* Will not occur for Modula-2 */
+ case STRUCTOP_PTR:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("->", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ return;
+
+ case BINOP_SUBSCRIPT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("[", stream);
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ fputs_filtered ("]", stream);
+ return;
+
+ case UNOP_POSTINCREMENT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("++", stream);
+ return;
+
+ case UNOP_POSTDECREMENT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("--", stream);
+ return;
+
+ case UNOP_CAST:
+ (*pos) += 2;
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered ("(", stream);
+ fputs_filtered ("(", stream);
+ type_print (exp->elts[pc + 1].type, "", stream, 0);
+ fputs_filtered (") ", stream);
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered (")", stream);
+ return;
+
+ case UNOP_MEMVAL:
+ (*pos) += 2;
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered ("(", stream);
+ if (exp->elts[pc + 1].type->code == TYPE_CODE_FUNC &&
+ exp->elts[pc + 3].opcode == OP_LONG) {
+ /* We have a minimal symbol fn, probably. It's encoded
+ as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address).
+ Swallow the OP_LONG (including both its opcodes); ignore
+ its type; print the value in the type of the MEMVAL. */
+ (*pos) += 4;
+ val = value_at_lazy (exp->elts[pc + 1].type,
+ (CORE_ADDR) exp->elts[pc + 5].longconst);
+ value_print (val, stream, 0, Val_no_prettyprint);
+ } else {
+ fputs_filtered ("{", stream);
+ type_print (exp->elts[pc + 1].type, "", stream, 0);
+ fputs_filtered ("} ", stream);
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ }
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered (")", stream);
+ return;
+
+ case BINOP_ASSIGN_MODIFY:
+ opcode = exp->elts[pc + 1].opcode;
+ (*pos) += 2;
+ myprec = PREC_ASSIGN;
+ assoc = 1;
+ assign_modify = 1;
+ op_str = "???";
+ for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
+ if (op_print_tab[tem].opcode == opcode)
+ {
+ op_str = op_print_tab[tem].string;
+ break;
+ }
+ if (op_print_tab[tem].opcode != opcode)
+ /* Not found; don't try to keep going because we don't know how
+ to interpret further elements. */
+ error ("Invalid expression");
+ break;
+
+ /* C++ ops */
+
+ case OP_THIS:
+ ++(*pos);
+ fputs_filtered ("this", stream);
+ return;
+
+ /* Modula-2 ops */
+
+ case MULTI_SUBSCRIPT:
+ (*pos) += 2;
+ nargs = longest_to_int (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 BINOP_VAL:
+ (*pos)+=2;
+ fprintf(stream,"VAL(");
+ type_print(exp->elts[pc+1].type,"",stream,0);
+ fprintf(stream,",");
+ print_subexp(exp,pos,stream,PREC_PREFIX);
+ fprintf(stream,")");
+ return;
+
+ case UNOP_CAP:
+ print_simple_m2_func("CAP",exp,pos,stream);
+ return;
+
+ case UNOP_CHR:
+ print_simple_m2_func("CHR",exp,pos,stream);
+ return;
+
+ case UNOP_ORD:
+ print_simple_m2_func("ORD",exp,pos,stream);
+ return;
+
+ case UNOP_ABS:
+ print_simple_m2_func("ABS",exp,pos,stream);
+ return;
+
+ case UNOP_FLOAT:
+ print_simple_m2_func("FLOAT",exp,pos,stream);
+ return;
+
+ case UNOP_HIGH:
+ print_simple_m2_func("HIGH",exp,pos,stream);
+ return;
+
+ case UNOP_MAX:
+ print_simple_m2_func("MAX",exp,pos,stream);
+ return;
+
+ case UNOP_MIN:
+ print_simple_m2_func("MIN",exp,pos,stream);
+ return;
+
+ case UNOP_ODD:
+ print_simple_m2_func("ODD",exp,pos,stream);
+ return;
+
+ case UNOP_TRUNC:
+ print_simple_m2_func("TRUNC",exp,pos,stream);
+ return;
+
+ case BINOP_INCL:
+ case BINOP_EXCL:
+ error("print_subexp: Not implemented.");
+
+ /* Default ops */
+
+ default:
+ op_str = "???";
+ for (tem = 0; op_print_tab[tem].opcode != OP_NULL; 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 (op_print_tab[tem].opcode != opcode)
+ /* Not found; don't try to keep going because we don't know how
+ to interpret further elements. For example, this happens
+ if opcode is OP_TYPE. */
+ error ("Invalid expression");
+ }
+
+ if ((int) myprec < (int) prec)
+ fputs_filtered ("(", stream);
+ if ((int) opcode > (int) BINOP_END)
+ {
+ /* Unary prefix operator. */
+ fputs_filtered (op_str, stream);
+ 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,
+ (enum precedence) ((int) myprec + assoc));
+ /* Print the operator itself. */
+ if (assign_modify)
+ fprintf_filtered (stream, " %s= ", op_str);
+ else if (op_str[0] == ',')
+ fprintf_filtered (stream, "%s ", op_str);
+ else
+ fprintf_filtered (stream, " %s ", op_str);
+ /* Print right operand.
+ If operator is left-associative,
+ increment precedence for this operand. */
+ print_subexp (exp, pos, stream,
+ (enum precedence) ((int) myprec + !assoc));
+ }
+
+ if ((int) myprec < (int) prec)
+ fputs_filtered (")", stream);
+}
+
+/* Print out something of the form <s>(<arg>).
+ This is used to print out some builtin Modula-2
+ functions.
+ FIXME: There is probably some way to get the precedence
+ rules to do this (print a unary operand with parens around it). */
+static void
+print_simple_m2_func(s,exp,pos,stream)
+ char *s;
+ register struct expression *exp;
+ register int *pos;
+ FILE *stream;
+{
+ fprintf(stream,"%s(",s);
+ print_subexp(exp,pos,stream,PREC_PREFIX);
+ fprintf(stream,")");
+}
+
+/* Return the operator corresponding to opcode OP as
+ a string. NULL indicates that the opcode was not found in the
+ current language table. */
+char *
+op_string(op)
+ enum exp_opcode op;
+{
+ int tem;
+ register const struct op_print *op_print_tab;
+
+ op_print_tab = current_language->la_op_print_tab;
+ for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
+ if (op_print_tab[tem].opcode == op)
+ return op_print_tab[tem].string;
+ return NULL;
+}
+
+#ifdef DEBUG_EXPRESSIONS
+
+/* Support for dumping the raw data from expressions in a human readable
+ form. */
+
+void
+dump_expression (exp, stream, note)
+ struct expression *exp;
+ FILE *stream;
+ char *note;
+{
+ int elt;
+ char *opcode_name;
+ char *eltscan;
+ int eltsize;
+
+ fprintf_filtered (stream, "Dump of expression @ 0x%lx, %s:\n",
+ (unsigned long) exp, note);
+ fprintf_filtered (stream, "\tLanguage %s, %d elements, %d bytes each.\n",
+ exp->language_defn->la_name, exp -> nelts,
+ sizeof (union exp_element));
+ fprintf_filtered (stream, "\t%5s %20s %16s %s\n", "Index", "Opcode",
+ "Hex Value", "String Value");
+ for (elt = 0; elt < exp -> nelts; elt++)
+ {
+ fprintf_filtered (stream, "\t%5d ", elt);
+ switch (exp -> elts[elt].opcode)
+ {
+ default: opcode_name = "<unknown>"; break;
+ case OP_NULL: opcode_name = "OP_NULL"; break;
+ case BINOP_ADD: opcode_name = "BINOP_ADD"; break;
+ case BINOP_SUB: opcode_name = "BINOP_SUB"; break;
+ case BINOP_MUL: opcode_name = "BINOP_MUL"; break;
+ case BINOP_DIV: opcode_name = "BINOP_DIV"; break;
+ case BINOP_REM: opcode_name = "BINOP_REM"; break;
+ case BINOP_MOD: opcode_name = "BINOP_MOD"; break;
+ case BINOP_LSH: opcode_name = "BINOP_LSH"; break;
+ case BINOP_RSH: opcode_name = "BINOP_RSH"; break;
+ case BINOP_LOGICAL_AND: opcode_name = "BINOP_LOGICAL_AND"; break;
+ case BINOP_LOGICAL_OR: opcode_name = "BINOP_LOGICAL_OR"; break;
+ case BINOP_BITWISE_AND: opcode_name = "BINOP_BITWISE_AND"; break;
+ case BINOP_BITWISE_IOR: opcode_name = "BINOP_BITWISE_IOR"; break;
+ case BINOP_BITWISE_XOR: opcode_name = "BINOP_BITWISE_XOR"; break;
+ case BINOP_EQUAL: opcode_name = "BINOP_EQUAL"; break;
+ case BINOP_NOTEQUAL: opcode_name = "BINOP_NOTEQUAL"; break;
+ case BINOP_LESS: opcode_name = "BINOP_LESS"; break;
+ case BINOP_GTR: opcode_name = "BINOP_GTR"; break;
+ case BINOP_LEQ: opcode_name = "BINOP_LEQ"; break;
+ case BINOP_GEQ: opcode_name = "BINOP_GEQ"; break;
+ case BINOP_REPEAT: opcode_name = "BINOP_REPEAT"; break;
+ case BINOP_ASSIGN: opcode_name = "BINOP_ASSIGN"; break;
+ case BINOP_COMMA: opcode_name = "BINOP_COMMA"; break;
+ case BINOP_SUBSCRIPT: opcode_name = "BINOP_SUBSCRIPT"; break;
+ case MULTI_SUBSCRIPT: opcode_name = "MULTI_SUBSCRIPT"; break;
+ case BINOP_EXP: opcode_name = "BINOP_EXP"; break;
+ case BINOP_MIN: opcode_name = "BINOP_MIN"; break;
+ case BINOP_MAX: opcode_name = "BINOP_MAX"; break;
+ case BINOP_SCOPE: opcode_name = "BINOP_SCOPE"; break;
+ case STRUCTOP_MEMBER: opcode_name = "STRUCTOP_MEMBER"; break;
+ case STRUCTOP_MPTR: opcode_name = "STRUCTOP_MPTR"; break;
+ case BINOP_INTDIV: opcode_name = "BINOP_INTDIV"; break;
+ case BINOP_ASSIGN_MODIFY: opcode_name = "BINOP_ASSIGN_MODIFY"; break;
+ case BINOP_VAL: opcode_name = "BINOP_VAL"; break;
+ case BINOP_INCL: opcode_name = "BINOP_INCL"; break;
+ case BINOP_EXCL: opcode_name = "BINOP_EXCL"; break;
+ case BINOP_CONCAT: opcode_name = "BINOP_CONCAT"; break;
+ case BINOP_END: opcode_name = "BINOP_END"; break;
+ case TERNOP_COND: opcode_name = "TERNOP_COND"; break;
+ case OP_LONG: opcode_name = "OP_LONG"; break;
+ case OP_DOUBLE: opcode_name = "OP_DOUBLE"; break;
+ case OP_VAR_VALUE: opcode_name = "OP_VAR_VALUE"; break;
+ case OP_LAST: opcode_name = "OP_LAST"; break;
+ case OP_REGISTER: opcode_name = "OP_REGISTER"; break;
+ case OP_INTERNALVAR: opcode_name = "OP_INTERNALVAR"; break;
+ case OP_FUNCALL: opcode_name = "OP_FUNCALL"; break;
+ case OP_STRING: opcode_name = "OP_STRING"; break;
+ case OP_BITSTRING: opcode_name = "OP_BITSTRING"; break;
+ case OP_ARRAY: opcode_name = "OP_ARRAY"; break;
+ case UNOP_CAST: opcode_name = "UNOP_CAST"; break;
+ case UNOP_MEMVAL: opcode_name = "UNOP_MEMVAL"; break;
+ case UNOP_NEG: opcode_name = "UNOP_NEG"; break;
+ case UNOP_LOGICAL_NOT: opcode_name = "UNOP_LOGICAL_NOT"; break;
+ case UNOP_COMPLEMENT: opcode_name = "UNOP_COMPLEMENT"; break;
+ case UNOP_IND: opcode_name = "UNOP_IND"; break;
+ case UNOP_ADDR: opcode_name = "UNOP_ADDR"; break;
+ case UNOP_PREINCREMENT: opcode_name = "UNOP_PREINCREMENT"; break;
+ case UNOP_POSTINCREMENT: opcode_name = "UNOP_POSTINCREMENT"; break;
+ case UNOP_PREDECREMENT: opcode_name = "UNOP_PREDECREMENT"; break;
+ case UNOP_POSTDECREMENT: opcode_name = "UNOP_POSTDECREMENT"; break;
+ case UNOP_SIZEOF: opcode_name = "UNOP_SIZEOF"; break;
+ case UNOP_PLUS: opcode_name = "UNOP_PLUS"; break;
+ case UNOP_CAP: opcode_name = "UNOP_CAP"; break;
+ case UNOP_CHR: opcode_name = "UNOP_CHR"; break;
+ case UNOP_ORD: opcode_name = "UNOP_ORD"; break;
+ case UNOP_ABS: opcode_name = "UNOP_ABS"; break;
+ case UNOP_FLOAT: opcode_name = "UNOP_FLOAT"; break;
+ case UNOP_HIGH: opcode_name = "UNOP_HIGH"; break;
+ case UNOP_MAX: opcode_name = "UNOP_MAX"; break;
+ case UNOP_MIN: opcode_name = "UNOP_MIN"; break;
+ case UNOP_ODD: opcode_name = "UNOP_ODD"; break;
+ case UNOP_TRUNC: opcode_name = "UNOP_TRUNC"; break;
+ case OP_BOOL: opcode_name = "OP_BOOL"; break;
+ case OP_M2_STRING: opcode_name = "OP_M2_STRING"; break;
+ case STRUCTOP_STRUCT: opcode_name = "STRUCTOP_STRUCT"; break;
+ case STRUCTOP_PTR: opcode_name = "STRUCTOP_PTR"; break;
+ case OP_THIS: opcode_name = "OP_THIS"; break;
+ case OP_SCOPE: opcode_name = "OP_SCOPE"; break;
+ case OP_TYPE: opcode_name = "OP_TYPE"; break;
+ }
+ fprintf_filtered (stream, "%20s ", opcode_name);
+ fprintf_filtered (stream,
+#if defined (PRINTF_HAS_LONG_LONG)
+ "%ll16x ",
+#else
+ "%l16x ",
+#endif
+ exp -> elts[elt].longconst);
+
+ for (eltscan = (char *) &exp->elts[elt],
+ eltsize = sizeof (union exp_element) ;
+ eltsize-- > 0;
+ eltscan++)
+ {
+ fprintf_filtered (stream, "%c",
+ isprint (*eltscan) ? (*eltscan & 0xFF) : '.');
+ }
+ fprintf_filtered (stream, "\n");
+ }
+}
+
+#endif /* DEBUG_EXPRESSIONS */
diff --git a/gnu/usr.bin/gdb/expression.h b/gnu/usr.bin/gdb/gdb/expression.h
index 5a5e20e0606c..521c25cb45a4 100644
--- a/gnu/usr.bin/gdb/expression.h
+++ b/gnu/usr.bin/gdb/gdb/expression.h
@@ -1,21 +1,28 @@
/* Definitions for expressions stored in reversed prefix form, for GDB.
- Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+ Copyright 1986, 1989, 1992 Free Software Foundation, Inc.
This file is part of GDB.
-GDB is free software; you can redistribute it and/or modify
+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.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (EXPRESSION_H)
+#define EXPRESSION_H 1
+
+#ifdef __STDC__
+struct block; /* Forward declaration for prototypes */
+#endif
/* Definitions for saved C expressions. */
@@ -34,6 +41,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
enum exp_opcode
{
+ /* Used when it's necessary to pass an opcode which will be ignored,
+ or to catch uninitialized values. */
+ OP_NULL,
+
/* BINOP_... operate on two values computed by following subexpressions,
replacing them by one result value. They take no immediate arguments. */
BINOP_ADD, /* + */
@@ -41,13 +52,14 @@ enum exp_opcode
BINOP_MUL, /* * */
BINOP_DIV, /* / */
BINOP_REM, /* % */
+ BINOP_MOD, /* mod (Knuth 1.2.4) */
BINOP_LSH, /* << */
BINOP_RSH, /* >> */
- BINOP_AND, /* && */
- BINOP_OR, /* || */
- BINOP_LOGAND, /* & */
- BINOP_LOGIOR, /* | */
- BINOP_LOGXOR, /* ^ */
+ BINOP_LOGICAL_AND, /* && */
+ BINOP_LOGICAL_OR, /* || */
+ BINOP_BITWISE_AND, /* & */
+ BINOP_BITWISE_IOR, /* | */
+ BINOP_BITWISE_XOR, /* ^ */
BINOP_EQUAL, /* == */
BINOP_NOTEQUAL, /* != */
BINOP_LESS, /* < */
@@ -73,7 +85,8 @@ enum exp_opcode
STRUCTOP_MPTR,
/* end of C++. */
- BINOP_END,
+ /* For Modula-2 integer division DIV */
+ BINOP_INTDIV,
BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
The following exp_element is another opcode,
@@ -81,9 +94,30 @@ enum exp_opcode
Then comes another BINOP_ASSIGN_MODIFY,
making three exp_elements in total. */
+ /* Modula-2 standard (binary) procedures*/
+ BINOP_VAL,
+ BINOP_INCL,
+ BINOP_EXCL,
+
+ /* Concatenate two operands, such as character strings or bitstrings.
+ If the first operand is a integer expression, then it means concatenate
+ the second operand with itself that many times. */
+ BINOP_CONCAT,
+
+ /* This must be the highest BINOP_ value, for expprint.c. */
+ BINOP_END,
+
/* Operates on three values computed by following subexpressions. */
TERNOP_COND, /* ?: */
+/* Multidimensional subscript operator, such as Modula-2 x[a,b,...].
+ The dimensionality is encoded in the operator, like the number of
+ function arguments in OP_FUNCALL, I.E. <OP><dimension><OP>.
+ The value of the first following subexpression is subscripted
+ by each of the next following subexpressions, one per dimension. */
+
+ MULTI_SUBSCRIPT,
+
/* 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. */
@@ -96,9 +130,15 @@ enum exp_opcode
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 takes one struct block * in the following element,
+ and one struct symbol * in the following exp_element, followed by
+ another OP_VAR_VALUE, making four exp_elements. If the block is
+ non-NULL, evaluate the symbol relative to the innermost frame
+ executing in that block; if the block is NULL use the selected frame. */
+
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.
@@ -123,6 +163,21 @@ enum exp_opcode
data is just made into a string constant when the operation
is executed. */
OP_STRING,
+/* OP_BITSTRING represents a packed bitstring constant.
+ Its format is the same as that of a STRUCTOP, but the bitstring
+ data is just made into a bitstring constant when the operation
+ is executed. */
+ OP_BITSTRING,
+/* OP_ARRAY creates an array constant out of the following subexpressions.
+ It is followed by two exp_elements, the first containing an integer
+ that is the lower bound of the array and the second containing another
+ integer that is the upper bound of the array. The second integer is
+ followed by a repeat of OP_ARRAY, making four exp_elements total.
+ The bounds are used to compute the number of following subexpressions
+ to consume, as well as setting the bounds in the created array constant.
+ The type of the elements is taken from the type of the first subexp,
+ and they must all match. */
+ OP_ARRAY,
/* 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.
@@ -136,8 +191,8 @@ enum exp_opcode
/* 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_LOGICAL_NOT, /* Unary ! */
+ UNOP_COMPLEMENT, /* Unary ~ */
UNOP_IND, /* Unary * */
UNOP_ADDR, /* Unary & */
UNOP_PREINCREMENT, /* ++ before an expression */
@@ -146,6 +201,22 @@ enum exp_opcode
UNOP_POSTDECREMENT, /* -- after an expression */
UNOP_SIZEOF, /* Unary sizeof (followed by expression) */
+ UNOP_PLUS, /* Unary plus */
+
+ UNOP_CAP, /* Modula-2 standard (unary) procedures */
+ UNOP_CHR,
+ UNOP_ORD,
+ UNOP_ABS,
+ UNOP_FLOAT,
+ UNOP_HIGH,
+ UNOP_MAX,
+ UNOP_MIN,
+ UNOP_ODD,
+ UNOP_TRUNC,
+
+ OP_BOOL, /* Modula-2 builtin BOOLEAN type */
+ OP_M2_STRING, /* Modula-2 string constants */
+
/* 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).
@@ -153,8 +224,10 @@ enum exp_opcode
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. */
+ The length of the string follows the opcode, followed by
+ BYTES_TO_EXP_ELEM(length) elements containing the data of the
+ string, followed by the length again and the opcode again. */
+
STRUCTOP_STRUCT,
STRUCTOP_PTR,
@@ -168,6 +241,10 @@ enum exp_opcode
a string, which, of course, is variable length. */
OP_SCOPE,
+ /* OP_TYPE is for parsing types, and used with the "ptype" command
+ so we can look up types that are qualified by scope, either with
+ the GDB "::" operator, or the Modula-2 '.' operator. */
+ OP_TYPE
};
union exp_element
@@ -176,16 +253,61 @@ union exp_element
struct symbol *symbol;
LONGEST longconst;
double doubleconst;
+ /* Really sizeof (union exp_element) characters (or less for the last
+ element of a string). */
char string;
struct type *type;
struct internalvar *internalvar;
+ struct block *block;
};
struct expression
{
+ const struct language_defn *language_defn; /* language it was entered in */
int nelts;
union exp_element elts[1];
};
-struct expression *parse_c_expression ();
-struct expression *parse_c_1 ();
+/* Macros for converting between number of expression elements and bytes
+ to store that many expression elements. */
+
+#define EXP_ELEM_TO_BYTES(elements) \
+ ((elements) * sizeof (union exp_element))
+#define BYTES_TO_EXP_ELEM(bytes) \
+ (((bytes) + sizeof (union exp_element) - 1) / sizeof (union exp_element))
+
+/* From parse.c */
+
+extern struct expression *
+parse_expression PARAMS ((char *));
+
+extern struct expression *
+parse_exp_1 PARAMS ((char **, struct block *, int));
+
+/* 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_<whatever>, then look at it. */
+extern struct block *innermost_block;
+
+/* From expprint.c */
+
+extern void
+print_expression PARAMS ((struct expression *, FILE *));
+
+extern char *
+op_string PARAMS ((enum exp_opcode));
+
+/* To enable dumping of all parsed expressions in a human readable
+ form, define DEBUG_EXPRESSIONS. This is a compile time constant
+ at the moment, since it's not clear that this feature is important
+ enough to include by default. */
+
+#ifdef DEBUG_EXPRESSIONS
+extern void
+dump_expression PARAMS ((struct expression *, FILE *, char *));
+#define DUMP_EXPRESSION(exp,file,note) dump_expression ((exp), (file), (note))
+#else
+#define DUMP_EXPRESSION(exp,file,note) /* Null expansion */
+#endif /* DEBUG_EXPRESSIONS */
+
+#endif /* !defined (EXPRESSION_H) */
diff --git a/gnu/usr.bin/gdb/gdb/findvar.c b/gnu/usr.bin/gdb/gdb/findvar.c
new file mode 100644
index 000000000000..bf50e1f04541
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/findvar.c
@@ -0,0 +1,971 @@
+/* Find a variable's value in memory, for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "frame.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "inferior.h"
+#include "target.h"
+
+/* Basic byte-swapping routines. GDB has needed these for a long time...
+ All extract a target-format integer at ADDR which is LEN bytes long. */
+
+#if TARGET_CHAR_BIT != 8 || HOST_CHAR_BIT != 8
+ /* 8 bit characters are a pretty safe assumption these days, so we
+ assume it throughout all these swapping routines. If we had to deal with
+ 9 bit characters, we would need to make len be in bits and would have
+ to re-write these routines... */
+ you lose
+#endif
+
+LONGEST
+extract_signed_integer (addr, len)
+ PTR addr;
+ int len;
+{
+ LONGEST retval;
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ if (len > sizeof (LONGEST))
+ error ("\
+That operation is not available on integers of more than %d bytes.",
+ sizeof (LONGEST));
+
+ /* Start at the most significant end of the integer, and work towards
+ the least significant. */
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+ p = startaddr;
+#else
+ p = endaddr - 1;
+#endif
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST)*p ^ 0x80) - 0x80;
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+ for (++p; p < endaddr; ++p)
+#else
+ for (--p; p >= startaddr; --p)
+#endif
+ {
+ retval = (retval << 8) | *p;
+ }
+ return retval;
+}
+
+unsigned LONGEST
+extract_unsigned_integer (addr, len)
+ PTR addr;
+ int len;
+{
+ unsigned LONGEST retval;
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ if (len > sizeof (unsigned LONGEST))
+ error ("\
+That operation is not available on integers of more than %d bytes.",
+ sizeof (unsigned LONGEST));
+
+ /* Start at the most significant end of the integer, and work towards
+ the least significant. */
+ retval = 0;
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+ for (p = startaddr; p < endaddr; ++p)
+#else
+ for (p = endaddr - 1; p >= startaddr; --p)
+#endif
+ {
+ retval = (retval << 8) | *p;
+ }
+ return retval;
+}
+
+CORE_ADDR
+extract_address (addr, len)
+ PTR addr;
+ int len;
+{
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+ return extract_unsigned_integer (addr, len);
+}
+
+void
+store_signed_integer (addr, len, val)
+ PTR addr;
+ int len;
+ LONGEST val;
+{
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ /* Start at the least significant end of the integer, and work towards
+ the most significant. */
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+ for (p = endaddr - 1; p >= startaddr; --p)
+#else
+ for (p = startaddr; p < endaddr; ++p)
+#endif
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+}
+
+void
+store_unsigned_integer (addr, len, val)
+ PTR addr;
+ int len;
+ unsigned LONGEST val;
+{
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ /* Start at the least significant end of the integer, and work towards
+ the most significant. */
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+ for (p = endaddr - 1; p >= startaddr; --p)
+#else
+ for (p = startaddr; p < endaddr; ++p)
+#endif
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+}
+
+void
+store_address (addr, len, val)
+ PTR addr;
+ int len;
+ CORE_ADDR val;
+{
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+ store_unsigned_integer (addr, len, (LONGEST)val);
+}
+
+#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,
+ target format) 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 != 0)
+ {
+ if (lval != NULL)
+ *lval = lval_memory;
+ if (regnum == SP_REGNUM)
+ {
+ if (raw_buffer != NULL)
+ {
+ /* Put it back in target format. */
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), 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)
+ {
+ /* Put it back in target format. */
+ store_address (myaddr, REGISTER_RAW_SIZE(FP_REGNUM),
+ FRAME_FP(selected_frame));
+ 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);
+
+ REGISTER_CONVERT_TO_VIRTUAL (regnum, raw_buffer, virtual_buffer);
+ val = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+ memcpy (VALUE_CONTENTS_RAW (val), virtual_buffer,
+ REGISTER_VIRTUAL_SIZE (regnum));
+ VALUE_LVAL (val) = lval;
+ VALUE_ADDRESS (val) = addr;
+ VALUE_REGNO (val) = regnum;
+ VALUE_OPTIMIZED_OUT (val) = optim;
+ return val;
+}
+
+/* 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 memcpy'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)
+ memcpy (myaddr, &registers[regbyte], len);
+}
+
+/* Read register REGNO into memory at MYADDR, which must be large enough
+ for REGISTER_RAW_BYTES (REGNO). Target byte-order.
+ 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);
+ memcpy (myaddr, &registers[REGISTER_BYTE (regno)],
+ 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);
+ memcpy (&registers[regbyte], myaddr, len);
+ target_store_registers (-1);
+}
+
+/* Return the raw contents of register REGNO, regarding it as an integer. */
+/* This probably should be returning LONGEST rather than CORE_ADDR. */
+
+CORE_ADDR
+read_register (regno)
+ int regno;
+{
+ if (!register_valid[regno])
+ target_fetch_registers (regno);
+
+ return extract_address (&registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE(regno));
+}
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* Store VALUE, into the raw contents of register number REGNO. */
+/* FIXME: The val arg should probably be a LONGEST. */
+
+void
+write_register (regno, val)
+ int regno;
+ LONGEST val;
+{
+ PTR buf;
+ int size;
+
+ /* 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;
+
+ size = REGISTER_RAW_SIZE(regno);
+ buf = alloca (size);
+ store_signed_integer (buf, size, (LONGEST) val);
+
+ /* If we have a valid copy of the register, and new value == old value,
+ then don't bother doing the actual store. */
+
+ if (register_valid [regno])
+ {
+ if (memcmp (&registers[REGISTER_BYTE (regno)], buf, size) == 0)
+ return;
+ }
+
+ target_prepare_to_store ();
+
+ memcpy (&registers[REGISTER_BYTE (regno)], buf, size);
+
+ register_valid [regno] = 1;
+
+ 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;
+ memcpy (&registers[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
+
+ /* On some architectures, e.g. HPPA, there are a few stray bits in some
+ registers, that the rest of the code would like to ignore. */
+#ifdef CLEAN_UP_REGISTER_VALUE
+ CLEAN_UP_REGISTER_VALUE(regno, &registers[REGISTER_BYTE(regno)]);
+#endif
+}
+
+/* Will calling read_var_value or locate_var_value on SYM end
+ up caring what frame it is being evaluated relative to? SYM must
+ be non-NULL. */
+int
+symbol_read_needs_frame (sym)
+ struct symbol *sym;
+{
+ switch (SYMBOL_CLASS (sym))
+ {
+ /* All cases listed explicitly so that gcc -Wall will detect it if
+ we failed to consider one. */
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ return 1;
+
+ case LOC_UNDEF:
+ case LOC_CONST:
+ case LOC_STATIC:
+ case LOC_TYPEDEF:
+
+ case LOC_LABEL:
+ /* Getting the address of a label can be done independently of the block,
+ even if some *uses* of that address wouldn't work so well without
+ the right frame. */
+
+ case LOC_BLOCK:
+ case LOC_CONST_BYTES:
+ case LOC_OPTIMIZED_OUT:
+ return 0;
+ }
+}
+
+/* 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.
+ If FRAME is NULL, use the selected_frame. */
+
+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;
+ 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:
+ /* Put the constant back in target format. */
+ store_signed_integer (VALUE_CONTENTS_RAW (v), len,
+ (LONGEST) SYMBOL_VALUE (var));
+ VALUE_LVAL (v) = not_lval;
+ return v;
+
+ case LOC_LABEL:
+ /* Put the constant back in target format. */
+ store_address (VALUE_CONTENTS_RAW (v), len, SYMBOL_VALUE_ADDRESS (var));
+ VALUE_LVAL (v) = not_lval;
+ return v;
+
+ case LOC_CONST_BYTES:
+ {
+ char *bytes_addr;
+ bytes_addr = SYMBOL_VALUE_BYTES (var);
+ memcpy (VALUE_CONTENTS_RAW (v), bytes_addr, len);
+ VALUE_LVAL (v) = not_lval;
+ return v;
+ }
+
+ case LOC_STATIC:
+ addr = SYMBOL_VALUE_ADDRESS (var);
+ break;
+
+ case LOC_ARG:
+ fi = get_frame_info (frame);
+ if (fi == NULL)
+ return 0;
+ addr = FRAME_ARGS_ADDRESS (fi);
+ if (!addr)
+ {
+ return 0;
+ }
+ addr += SYMBOL_VALUE (var);
+ break;
+
+ case LOC_REF_ARG:
+ fi = get_frame_info (frame);
+ if (fi == NULL)
+ return 0;
+ addr = FRAME_ARGS_ADDRESS (fi);
+ if (!addr)
+ {
+ return 0;
+ }
+ addr += SYMBOL_VALUE (var);
+ addr = read_memory_unsigned_integer
+ (addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ break;
+
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ fi = get_frame_info (frame);
+ if (fi == NULL)
+ return 0;
+ addr = FRAME_LOCALS_ADDRESS (fi);
+ addr += SYMBOL_VALUE (var);
+ break;
+
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ get_saved_register (buf, NULL, NULL, frame, SYMBOL_BASEREG (var),
+ NULL);
+ addr = extract_address (buf, REGISTER_RAW_SIZE (SYMBOL_BASEREG (var)));
+ addr += SYMBOL_VALUE (var);
+ 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:
+ case LOC_REGPARM_ADDR:
+ {
+ struct block *b;
+
+ if (frame == NULL)
+ return 0;
+ b = get_frame_block (frame);
+
+ v = value_from_register (type, SYMBOL_VALUE (var), frame);
+
+ if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
+ {
+ addr = *(CORE_ADDR *)VALUE_CONTENTS (v);
+ VALUE_LVAL (v) = lval_memory;
+ }
+ else
+ return v;
+ }
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ VALUE_LVAL (v) = not_lval;
+ VALUE_OPTIMIZED_OUT (v) = 1;
+ return v;
+
+ 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
+#ifdef GDB_TARGET_IS_H8500
+ || TYPE_CODE (type) == TYPE_CODE_PTR
+#endif
+ )
+ {
+ /* 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 = 0;
+
+ value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE);
+
+ /* Copy all of the data out, whereever it may be. */
+
+#ifdef GDB_TARGET_IS_H8500
+/* This piece of hideosity is required because the H8500 treats registers
+ differently depending upon whether they are used as pointers or not. As a
+ pointer, a register needs to have a page register tacked onto the front.
+ An alternate way to do this would be to have gcc output different register
+ numbers for the pointer & non-pointer form of the register. But, it
+ doesn't, so we're stuck with this. */
+
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ && len > 2)
+ {
+ int page_regnum;
+
+ switch (regnum)
+ {
+ case R0_REGNUM: case R1_REGNUM: case R2_REGNUM: case R3_REGNUM:
+ page_regnum = SEG_D_REGNUM;
+ break;
+ case R4_REGNUM: case R5_REGNUM:
+ page_regnum = SEG_E_REGNUM;
+ break;
+ case R6_REGNUM: case R7_REGNUM:
+ page_regnum = SEG_T_REGNUM;
+ break;
+ }
+
+ value_bytes[0] = 0;
+ get_saved_register (value_bytes + 1,
+ &optim,
+ &addr,
+ frame,
+ page_regnum,
+ &lval);
+
+ if (lval == lval_register)
+ reg_stor++;
+ else
+ mem_stor++;
+ first_addr = addr;
+ last_addr = addr;
+
+ get_saved_register (value_bytes + 2,
+ &optim,
+ &addr,
+ frame,
+ regnum,
+ &lval);
+
+ if (lval == lval_register)
+ reg_stor++;
+ else
+ {
+ mem_stor++;
+ mem_tracking = mem_tracking && (addr == last_addr);
+ }
+ last_addr = addr;
+ }
+ else
+#endif /* GDB_TARGET_IS_H8500 */
+ 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 (regnum == local_regnum)
+ first_addr = addr;
+ if (lval == lval_register)
+ reg_stor++;
+ else
+ {
+ mem_stor++;
+
+ 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. */
+ memcpy (VALUE_CONTENTS_RAW (v), value_bytes, len);
+
+ /* Finally do any conversion necessary when extracting this
+ type from more than one register. */
+#ifdef REGISTER_CONVERT_TO_TYPE
+ REGISTER_CONVERT_TO_TYPE(regnum, type, VALUE_CONTENTS_RAW(v));
+#endif
+ 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.) */
+
+ REGISTER_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'. */
+ /* FIXME: This value will be not_lval, which means we can't assign
+ to it. Probably the right fix is to do the cast on a temporary
+ value, and just copy the VALUE_CONTENTS over. */
+ v = allocate_value (REGISTER_VIRTUAL_TYPE (regnum));
+ memcpy (VALUE_CONTENTS_RAW (v), virtual_buffer,
+ REGISTER_VIRTUAL_SIZE (regnum));
+ v = value_cast (type, v);
+ }
+ else
+ memcpy (VALUE_CONTENTS_RAW (v), virtual_buffer, 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
+
+ memcpy (VALUE_CONTENTS_RAW (v), virtual_buffer + VALUE_OFFSET (v), len);
+ }
+
+ return v;
+}
+
+/* Given a struct symbol for a variable or function,
+ and a stack frame id,
+ return a (pointer to a) struct value containing the properly typed
+ address. */
+
+value
+locate_var_value (var, frame)
+ register struct symbol *var;
+ FRAME frame;
+{
+ CORE_ADDR addr = 0;
+ struct type *type = SYMBOL_TYPE (var);
+ 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_SOURCE_NAME (var));
+
+ if (VALUE_LAZY (lazy_value)
+ || TYPE_CODE (type) == TYPE_CODE_FUNC)
+ {
+ addr = VALUE_ADDRESS (lazy_value);
+ return value_from_longest (lookup_pointer_type (type), (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_SOURCE_NAME (var));
+ break;
+
+ default:
+ error ("Can't take address of \"%s\" which isn't an lvalue.",
+ SYMBOL_SOURCE_NAME (var));
+ break;
+ }
+ return 0; /* For lint -- never reached */
+}
diff --git a/gnu/usr.bin/gdb/gdb/fopen-same.h b/gnu/usr.bin/gdb/gdb/fopen-same.h
new file mode 100644
index 000000000000..0f37529d33e0
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/fopen-same.h
@@ -0,0 +1,27 @@
+/* Macros for the 'type' part of an fopen, freopen or fdopen.
+
+ <Read|Write>[Update]<Binary file|text file>
+
+ This version is for "same" systems, where text and binary files are
+ the same. An example is Unix. Many Unix systems could also add a
+ "b" to the string, indicating binary files, but some reject this
+ (and thereby don't conform to ANSI C, but what else is new?).
+
+ This file is designed for inclusion by host-dependent .h files. No
+ user application should include it directly, since that would make
+ the application unable to be configured for both "same" and "binary"
+ variant systems. */
+
+#define FOPEN_RB "r"
+#define FOPEN_WB "w"
+#define FOPEN_AB "a"
+#define FOPEN_RUB "r+"
+#define FOPEN_WUB "w+"
+#define FOPEN_AUB "a+"
+
+#define FOPEN_RT "r"
+#define FOPEN_WT "w"
+#define FOPEN_AT "a"
+#define FOPEN_RUT "r+"
+#define FOPEN_WUT "w+"
+#define FOPEN_AUT "a+"
diff --git a/gnu/usr.bin/gdb/gdb/fork-child.c b/gnu/usr.bin/gdb/gdb/fork-child.c
new file mode 100644
index 000000000000..3c01b6021eb5
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/fork-child.c
@@ -0,0 +1,310 @@
+/* Fork a Unix child process, and set up to debug it, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "terminal.h"
+
+#include <signal.h>
+
+#ifdef SET_STACK_LIMIT_HUGE
+#include <sys/time.h>
+#include <sys/resource.h>
+
+extern int original_stack_limit;
+#endif /* SET_STACK_LIMIT_HUGE */
+
+extern char **environ;
+
+/* 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
+fork_inferior (exec_file, allargs, env, traceme_fun, init_trace_fun)
+ char *exec_file;
+ char *allargs;
+ char **env;
+ void (*traceme_fun) PARAMS ((void));
+ void (*init_trace_fun) PARAMS ((int));
+{
+ int pid;
+ char *shell_command;
+ char *shell_file;
+ static char default_shell_file[] = SHELL_FILE;
+ int len;
+ int pending_execs;
+ int terminal_initted;
+ /* 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;
+ char **save_our_env;
+
+ /* If no exec file handed to us, get it from the exec-file command -- with
+ a good, common error message if none is specified. */
+ if (exec_file == 0)
+ exec_file = get_exec_file(1);
+
+ /* 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;
+
+ /* Multiplying the length of exec_file by 4 is to account for the fact
+ that it may expand when quoted; it is a worst-case number based on
+ every character being '. */
+ len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop*/ 12;
+ /* 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 ");
+
+ /* Now add exec_file, quoting as necessary. */
+ {
+ char *p;
+ int need_to_quote;
+
+ /* Quoting in this style is said to work with all shells. But csh
+ on IRIX 4.0.1 can't deal with it. So we only quote it if we need
+ to. */
+ p = exec_file;
+ while (1)
+ {
+ switch (*p)
+ {
+ case '\'':
+ case '"':
+ case '(':
+ case ')':
+ case '$':
+ case '&':
+ case ';':
+ case '<':
+ case '>':
+ case ' ':
+ case '\n':
+ case '\t':
+ need_to_quote = 1;
+ goto end_scan;
+
+ case '\0':
+ need_to_quote = 0;
+ goto end_scan;
+
+ default:
+ break;
+ }
+ ++p;
+ }
+ end_scan:
+ if (need_to_quote)
+ {
+ strcat (shell_command, "'");
+ for (p = exec_file; *p != '\0'; ++p)
+ {
+ if (*p == '\'')
+ strcat (shell_command, "'\\''");
+ else
+ strncat (shell_command, p, 1);
+ }
+ strcat (shell_command, "'");
+ }
+ else
+ 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 ();
+
+ /* Retain a copy of our environment variables, since the child will
+ replace the value of environ and if we're vforked, we have to
+ restore it. */
+ save_our_env = environ;
+
+ /* Tell the terminal handling subsystem what tty we plan to run on;
+ it will just record the information for later. */
+
+ new_tty_prefork (inferior_io_terminal);
+
+ /* It is generally good practice to flush any possible pending stdio
+ output prior to doing a fork, to avoid the possibility of both the
+ parent and child flushing the same data after the fork. */
+
+ fflush (stdout);
+ fflush (stderr);
+
+#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);
+
+ /* Run inferior in a separate process group. */
+ debug_setpgrp = gdb_setpgid ();
+ if (debug_setpgrp == -1)
+ perror("setpgrp failed in child");
+
+#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 */
+
+ /* Ask the tty subsystem to switch to the one we specified earlier
+ (or to share the current terminal, if none was specified). */
+
+ new_tty ();
+
+ /* 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. */
+
+ /* "Trace me, Dr. Memory!" */
+ (*traceme_fun) ();
+
+ /* There is no execlpe call, so we have to set the environment
+ for our child in the global variable. If we've vforked, this
+ clobbers the parent, but environ is restored a few lines down
+ in the parent. By the way, yes we do need to look down the
+ path to find $SHELL. Rich Pixley says so, and I agree. */
+ environ = env;
+ execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", shell_file,
+ safe_strerror (errno));
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ /* Restore our environment in case a vforked child clob'd it. */
+ environ = save_our_env;
+
+ init_thread_list();
+
+ /* Now that we have a child process, make it our target, and
+ initialize anything target-vector-specific that needs initializing. */
+ (*init_trace_fun)(pid);
+
+ /* 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 ();
+
+ /* 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 ();
+
+ terminal_initted = 0;
+
+ 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 */
+ resume (0, stop_signal);
+ }
+ else
+ {
+ /* We handle SIGTRAP, however; it means child did an exec. */
+ if (!terminal_initted)
+ {
+ /* Now that the child has exec'd we know it has already set its
+ process group. On POSIX systems, tcsetpgrp will fail with
+ EPERM if we try it before the child's setpgid. */
+
+ /* 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 ();
+
+ terminal_initted = 1;
+ }
+ if (0 == --pending_execs)
+ break;
+ resume (0, 0); /* Just make it go on */
+ }
+ }
+ stop_soon_quietly = 0;
+
+ /* We are now in the child process of interest, having exec'd the
+ correct program, and are poised at the first instruction of the
+ new program. */
+#ifdef SOLIB_CREATE_INFERIOR_HOOK
+ SOLIB_CREATE_INFERIOR_HOOK (pid);
+#endif
+}
diff --git a/gnu/usr.bin/gdb/gdb/frame.h b/gnu/usr.bin/gdb/gdb/frame.h
new file mode 100644
index 000000000000..1fe6fb6a49b3
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/frame.h
@@ -0,0 +1,238 @@
+/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
+ Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (FRAME_H)
+#define FRAME_H 1
+
+/* A FRAME identifies a specific stack frame. It is not constant over
+ calls to the inferior (frame addresses are, see below).
+
+ This is implemented as a "struct frame_info *". This file and
+ blockframe.c are the only places which are allowed to use the
+ equivalence between FRAME and struct frame_info *. Exception:
+ Prototypes in other files use "struct frame_info *" because this
+ file might not be included.
+
+ The distinction between a FRAME and a "struct frame_info *" is made
+ with the idea of maybe someday changing a FRAME to be something else,
+ but seems to me that a "struct frame_info *" is fully general (since
+ any necessarily fields can be added; changing the meaning of existing
+ fields is not helped by the FRAME distinction), and this distinction
+ merely creates unnecessary hair. -kingdon, 18 May 93. */
+typedef struct frame_info *FRAME;
+
+/* Convert from a "struct frame_info *" into a FRAME. */
+#define FRAME_INFO_ID(f) (f)
+
+/* Convert from a FRAME into a "struct frame_info *". */
+extern struct frame_info *
+get_frame_info PARAMS ((FRAME));
+
+/* Type of the address of a frame. It is widely assumed (at least in
+ prototypes in headers which might not include this header) that
+ this is the same as CORE_ADDR, and no one can think of a case in
+ which it wouldn't be, so it might be best to remove this typedef. */
+typedef CORE_ADDR FRAME_ADDR;
+
+/* Convert from a FRAME into a frame address. Except in the
+ machine-dependent *FRAME* macros, a frame address has no defined
+ meaning other than as a magic cookie which identifies a frame over
+ calls to the inferior. The only known exception is inferior.h
+ (PC_IN_CALL_DUMMY) [ON_STACK]; see comments there. You cannot
+ assume that a frame address contains enough information to
+ reconstruct the frame; if you want more than just to identify the
+ frame (e.g. be able to fetch variables relative to that frame),
+ then save the whole struct frame_info (and the next struct
+ frame_info, since the latter is used for fetching variables on some
+ machines). */
+
+#define FRAME_FP(fr) ((fr)->frame)
+
+/* We keep a cache of stack frames, each of which is a "struct
+ frame_info". The innermost one gets allocated (in
+ wait_for_inferior) each time the inferior stops; current_frame
+ points to it. Additional frames get allocated (in
+ get_prev_frame_info) as needed, and are chained through the next
+ and prev fields. Any time that the frame cache becomes invalid
+ (most notably when we execute something, but also if we change how
+ we interpret the frames (e.g. "set heuristic-fence-post" in
+ mips-tdep.c, or anything which reads new symbols)), we should call
+ reinit_frame_cache. */
+
+struct frame_info
+ {
+ /* Nominal address of the frame described. See comments at FRAME_FP
+ about what this means outside the *FRAME* macros; in the *FRAME*
+ macros, it can mean whatever makes most sense for this machine. */
+ 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;
+
+ /* Nonzero if this is a frame associated with calling a signal handler.
+
+ Set by machine-dependent code. On some machines, if
+ the machine-dependent code fails to check for this, the backtrace
+ will look relatively normal. For example, on the i386
+ #3 0x158728 in sighold ()
+ On other machines (e.g. rs6000), the machine-dependent code better
+ set this to prevent us from trying to print it like a normal frame. */
+ int signal_handler_caller;
+
+ /* Anything extra for this structure that may have been defined
+ in the machine dependent files. */
+#ifdef EXTRA_FRAME_INFO
+ EXTRA_FRAME_INFO
+#endif
+
+ /* We should probably also store a "struct frame_saved_regs" here.
+ This is already done by some machines (e.g. config/m88k/tm-m88k.h)
+ but there is no reason it couldn't be general. */
+
+ /* Pointers to the next and previous frame_info's in the frame cache. */
+ 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.
+ This includes special registers such as pc and fp saved in
+ special ways in the stack frame. The SP_REGNUM is even more
+ special, the address here is the sp for the next frame, not the
+ address where the sp was saved. */
+
+ CORE_ADDR regs[NUM_REGS];
+ };
+
+/* Define a default FRAME_CHAIN_VALID, in the form that is suitable for most
+ targets. If FRAME_CHAIN_VALID returns zero it means that the given frame
+ is the outermost one and has no caller.
+
+ If a particular target needs a different definition, then it can override
+ the definition here by providing one in the tm file. */
+
+#if !defined (FRAME_CHAIN_VALID)
+
+#if defined (FRAME_CHAIN_VALID_ALTERNATE)
+
+/* Use the alternate method of avoiding running up off the end of the frame
+ chain or following frames back into the startup code. See the comments
+ in objfiles.h. */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ ((chain) != 0 \
+ && !inside_main_func ((thisframe) -> pc) \
+ && !inside_entry_func ((thisframe) -> pc))
+
+#else
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ ((chain) != 0 \
+ && !inside_entry_file (FRAME_SAVED_PC (thisframe)))
+
+#endif /* FRAME_CHAIN_VALID_ALTERNATE */
+
+#endif /* FRAME_CHAIN_VALID */
+
+/* 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;
+
+/* Level of the selected frame:
+ 0 for innermost, 1 for its caller, ...
+ or -1 for frame specified by address with no defined level. */
+
+extern int selected_frame_level;
+
+extern struct frame_info *
+get_prev_frame_info PARAMS ((FRAME));
+
+extern FRAME
+create_new_frame PARAMS ((FRAME_ADDR, CORE_ADDR));
+
+extern void
+flush_cached_frames PARAMS ((void));
+
+extern void
+reinit_frame_cache PARAMS ((void));
+
+extern void
+get_frame_saved_regs PARAMS ((struct frame_info *, struct frame_saved_regs *));
+
+extern void
+set_current_frame PARAMS ((FRAME));
+
+extern FRAME
+get_prev_frame PARAMS ((FRAME));
+
+extern FRAME
+get_current_frame PARAMS ((void));
+
+extern FRAME
+get_next_frame PARAMS ((FRAME));
+
+extern struct block *
+get_frame_block PARAMS ((FRAME));
+
+extern struct block *
+get_current_block PARAMS ((void));
+
+extern struct block *
+get_selected_block PARAMS ((void));
+
+extern struct symbol *
+get_frame_function PARAMS ((FRAME));
+
+extern CORE_ADDR
+get_frame_pc PARAMS ((FRAME));
+
+extern CORE_ADDR
+get_pc_function_start PARAMS ((CORE_ADDR));
+
+extern struct block * block_for_pc PARAMS ((CORE_ADDR));
+
+extern int frameless_look_for_prologue PARAMS ((FRAME));
+
+extern void print_frame_args PARAMS ((struct symbol *, struct frame_info *,
+ int, FILE *));
+
+extern FRAME find_relative_frame PARAMS ((FRAME, int*));
+
+extern void print_stack_frame PARAMS ((FRAME, int, int));
+
+extern void select_frame PARAMS ((FRAME, int));
+
+extern void record_selected_frame PARAMS ((FRAME_ADDR *, int *));
+
+extern void print_frame_info PARAMS ((struct frame_info *, int, int, int));
+
+extern CORE_ADDR find_saved_register PARAMS ((FRAME, int));
+
+extern FRAME block_innermost_frame PARAMS ((struct block *));
+
+extern CORE_ADDR sigtramp_saved_pc PARAMS ((FRAME));
+
+#endif /* !defined (FRAME_H) */
diff --git a/gnu/usr.bin/gdb/gdb/freebsd-nat.c b/gnu/usr.bin/gdb/gdb/freebsd-nat.c
new file mode 100644
index 000000000000..deb68ebb9453
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/freebsd-nat.c
@@ -0,0 +1,323 @@
+/* Native-dependent code for BSD Unix running on i386's, for GDB.
+ Copyright 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <machine/reg.h>
+
+/* this table must line up with REGISTER_NAMES in tm-i386.h */
+/* symbols like 'tEAX' come from <machine/reg.h> */
+static int tregmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ tESP, tEBP, tESI, tEDI,
+ tEIP, tEFLAGS, tCS, tSS
+};
+#ifdef sEAX
+static int sregmap[] =
+{
+ sEAX, sECX, sEDX, sEBX,
+ sESP, sEBP, sESI, sEDI,
+ sEIP, sEFLAGS, sCS, sSS
+};
+#endif
+/* blockend is the value of u.u_ar0, and points to the
+ place where ES is stored. */
+
+int
+i386_register_u_addr (blockend, regnum)
+ int blockend;
+ int regnum;
+{
+ /* The following condition is a kludge to get at the proper register map
+ depending upon the state of pcb_flag.
+ The proper condition would be
+ if (u.u_pcb.pcb_flag & FM_TRAP)
+ but that would require a ptrace call here and wouldn't work
+ for corefiles. */
+
+#ifdef sEAX
+ if (blockend < 0x1fcc)
+ return (blockend + 4 * tregmap[regnum]);
+ else
+ return (blockend + 4 * sregmap[regnum]);
+#else
+ return (blockend + 4 * tregmap[regnum]);
+#endif
+}
+
+#ifdef FLOAT_INFO
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <a.out.h>
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#define curpcb Xcurpcb /* XXX avoid leaking declaration from pcb.h */
+#include <sys/user.h>
+#undef curpcb
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/ptrace.h>
+
+#define fpstate save87
+#define U_FPSTATE(u) u.u_pcb.pcb_savefpu
+
+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];
+};
+
+void
+print_387_control_word (control)
+unsigned int 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);
+}
+
+void
+print_387_status_word (status)
+ unsigned int 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 ((unsigned int)status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf ("e: ");
+ print_387_status_word ((unsigned int)ep->status);
+ }
+
+ print_387_control_word ((unsigned int)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--)
+ {
+ int st_regno;
+ double val;
+
+ /* The physical regno `fpreg' is only relevant as an index into the
+ * tag word. Logical `%st' numbers are required for indexing `p->regs.
+ */
+ st_regno = (fpreg + 8 - top) & 0x7;
+
+ printf ("%%st(%d) %s ", st_regno, fpreg == top ? "=>" : " ");
+
+ 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[st_regno][i]);
+
+ i387_to_double (ep->regs[st_regno], (char *)&val);
+ printf (" %g\n", val);
+ }
+}
+
+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;
+ extern int inferior_pid;
+
+ uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
+ if (inferior_pid)
+ {
+ 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 (PT_READ_U, inferior_pid, (caddr_t)rounded_addr, 0);
+ rounded_addr += sizeof (int);
+ }
+ }
+ else
+ {
+ printf("float info: can't do a core file (yet)\n");
+
+ return;
+#if 0
+ 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;
+#endif
+ }
+
+ print_387_status (0, (struct env387 *)buf);
+}
+
+#endif
diff --git a/gnu/usr.bin/gdb/gdb/freebsd-solib.c b/gnu/usr.bin/gdb/gdb/freebsd-solib.c
new file mode 100644
index 000000000000..5b6e4c07309d
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/freebsd-solib.c
@@ -0,0 +1,1469 @@
+/* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+/* modified for FreeBSD, since the names in link.h are totally different!
+ 6.1.94 */
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <signal.h>
+#include <string.h>
+#ifndef SVR4_SHARED_LIBS
+ /* SunOS shared libs need the nlist structure. */
+#include <a.out.h>
+#endif
+#include <link.h>
+#include <sys/param.h>
+#include <fcntl.h>
+
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "target.h"
+#include "frame.h"
+#include "regex.h"
+#include "inferior.h"
+#include "language.h"
+
+#define MAX_PATH_SIZE 256 /* FIXME: Should be dynamic */
+
+/* On SVR4 systems, for the initial implementation, use some runtime startup
+ symbol as the "startup mapping complete" breakpoint address. The models
+ for SunOS and SVR4 dynamic linking debugger support are different in that
+ SunOS hits one breakpoint when all mapping is complete while using the SVR4
+ debugger support takes two breakpoint hits for each file mapped, and
+ there is no way to know when the "last" one is hit. Both these
+ mechanisms should be tied to a "breakpoint service routine" that
+ gets automatically executed whenever one of the breakpoints indicating
+ a change in mapping is hit. This is a future enhancement. (FIXME) */
+
+#define BKPT_AT_SYMBOL 1
+
+#if defined (BKPT_AT_SYMBOL) && defined (SVR4_SHARED_LIBS)
+static char *bkpt_names[] = {
+#ifdef SOLIB_BKPT_NAME
+ SOLIB_BKPT_NAME, /* Prefer configured name if it exists. */
+#endif
+ "_start",
+ "main",
+ NULL
+};
+#endif
+
+/* local data declarations */
+
+#ifndef SVR4_SHARED_LIBS
+
+#define DEBUG_BASE "_DYNAMIC"
+#ifdef OLD_FreeBSD_LD
+#define LM_ADDR(so) ((so) -> lm.lm_addr)
+#define LM_NEXT(so) ((so) -> lm.lm_next)
+#define LM_NAME(so) ((so) -> lm.lm_name)
+static struct link_dynamic dynamic_copy;
+static struct link_dynamic_2 ld_2_copy;
+static struct ld_debug debug_copy;
+#else
+#define LM_ADDR(so) ((so) -> lm.som_addr)
+#define LM_NEXT(so) ((so) -> lm.som_next)
+#define LM_NAME(so) ((so) -> lm.som_path)
+static struct _dynamic dynamic_copy;
+static struct section_dispatch_table ld_2_copy;
+static struct so_debug debug_copy;
+#endif
+static CORE_ADDR debug_addr;
+static CORE_ADDR flag_addr;
+
+#else /* SVR4_SHARED_LIBS */
+
+#define DEBUG_BASE "_r_debug"
+#define LM_ADDR(so) ((so) -> lm.l_addr)
+#define LM_NEXT(so) ((so) -> lm.l_next)
+#define LM_NAME(so) ((so) -> lm.l_name)
+static struct r_debug debug_copy;
+char shadow_contents[BREAKPOINT_MAX]; /* Stash old bkpt addr contents */
+
+#endif /* !SVR4_SHARED_LIBS */
+
+struct so_list {
+ struct so_list *next; /* next structure in linked list */
+#ifdef OLD_FreeBSD_LD
+ struct link_map lm; /* copy of link map from inferior */
+ struct link_map *lmaddr; /* addr in inferior lm was read from */
+#else
+ struct so_map lm; /* copy of link map from inferior */
+ struct so_map *lmaddr; /* addr in inferior lm was read from */
+#endif
+ CORE_ADDR lmend; /* upper addr bound of mapped object */
+ char so_name[MAX_PATH_SIZE]; /* shared object lib name (FIXME) */
+ char symbols_loaded; /* flag: symbols read in yet? */
+ char from_tty; /* flag: print msgs? */
+ struct objfile *objfile; /* objfile for loaded lib */
+ struct section_table *sections;
+ struct section_table *sections_end;
+ struct section_table *textsection;
+ bfd *abfd;
+};
+
+static struct so_list *so_list_head; /* List of known shared objects */
+static CORE_ADDR debug_base; /* Base of dynamic linker structures */
+static CORE_ADDR breakpoint_addr; /* Address where end bkpt is set */
+
+extern int
+fdmatch PARAMS ((int, int)); /* In libiberty */
+
+/* Local function prototypes */
+
+static void
+special_symbol_handling PARAMS ((struct so_list *));
+
+static void
+sharedlibrary_command PARAMS ((char *, int));
+
+static int
+enable_break PARAMS ((void));
+
+static int
+disable_break PARAMS ((void));
+
+static void
+info_sharedlibrary_command PARAMS ((char *, int));
+
+static int
+symbol_add_stub PARAMS ((char *));
+
+static struct so_list *
+find_solib PARAMS ((struct so_list *));
+
+#ifdef OLD_FreeBSD_LD
+static struct link_map *
+#else
+static struct so_map *
+#endif
+first_link_map_member PARAMS ((void));
+
+static CORE_ADDR
+locate_base PARAMS ((void));
+
+static void
+solib_map_sections PARAMS ((struct so_list *));
+
+#ifdef SVR4_SHARED_LIBS
+
+static int
+look_for_base PARAMS ((int, CORE_ADDR));
+
+static CORE_ADDR
+bfd_lookup_symbol PARAMS ((bfd *, char *));
+
+#else
+
+static void
+solib_add_common_symbols PARAMS ((struct rt_symbol *, struct objfile *));
+
+#endif
+
+/*
+
+LOCAL FUNCTION
+
+ solib_map_sections -- open bfd and build sections for shared lib
+
+SYNOPSIS
+
+ static void solib_map_sections (struct so_list *so)
+
+DESCRIPTION
+
+ Given a pointer to one of the shared objects in our list
+ of mapped objects, use the recorded name to open a bfd
+ descriptor for the object, build a section table, and then
+ relocate all the section addresses by the base address at
+ which the shared object was mapped.
+
+FIXMES
+
+ In most (all?) cases the shared object file name recorded in the
+ dynamic linkage tables will be a fully qualified pathname. For
+ cases where it isn't, do we really mimic the systems search
+ mechanism correctly in the below code (particularly the tilde
+ expansion stuff?).
+ */
+
+static void
+solib_map_sections (so)
+ struct so_list *so;
+{
+ char *filename;
+ char *scratch_pathname;
+ int scratch_chan;
+ struct section_table *p;
+ struct cleanup *old_chain;
+ bfd *abfd;
+
+ filename = tilde_expand (so -> so_name);
+ old_chain = make_cleanup (free, filename);
+
+ scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &scratch_pathname);
+ if (scratch_chan < 0)
+ {
+ scratch_chan = openp (getenv ("LD_LIBRARY_PATH"), 1, filename,
+ O_RDONLY, 0, &scratch_pathname);
+ }
+ if (scratch_chan < 0)
+ {
+ perror_with_name (filename);
+ }
+ /* Leave scratch_pathname allocated. abfd->name will point to it. */
+
+ abfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
+ if (!abfd)
+ {
+ close (scratch_chan);
+ error ("Could not open `%s' as an executable file: %s",
+ scratch_pathname, bfd_errmsg (bfd_error));
+ }
+ /* Leave bfd open, core_xfer_memory and "info files" need it. */
+ so -> abfd = abfd;
+ abfd -> cacheable = true;
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ error ("\"%s\": not in executable format: %s.",
+ scratch_pathname, bfd_errmsg (bfd_error));
+ }
+ if (build_section_table (abfd, &so -> sections, &so -> sections_end))
+ {
+ error ("Can't find the file sections in `%s': %s",
+ bfd_get_filename (exec_bfd), bfd_errmsg (bfd_error));
+ }
+
+ for (p = so -> sections; p < so -> sections_end; p++)
+ {
+ /* Relocate the section binding addresses as recorded in the shared
+ object's file by the base address to which the object was actually
+ mapped. */
+ p -> addr += (CORE_ADDR) LM_ADDR (so);
+ p -> endaddr += (CORE_ADDR) LM_ADDR (so);
+ so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
+ if (STREQ (p -> sec_ptr -> name, ".text"))
+ {
+ so -> textsection = p;
+ }
+ }
+
+ /* Free the file names, close the file now. */
+ do_cleanups (old_chain);
+}
+
+/* Read all dynamically loaded common symbol definitions from the inferior
+ and add them to the minimal symbol table for the shared library objfile. */
+
+#ifndef SVR4_SHARED_LIBS
+
+/* In GDB 4.9 this routine was a real performance hog. According to
+ some gprof data which mtranle@paris.IntelliCorp.COM (Minh Tran-Le)
+ sent, almost all the time spend in solib_add (up to 20 minutes with
+ 35 shared libraries) was spent here, with 5/6 in
+ lookup_minimal_symbol and 1/6 in read_memory.
+
+ To fix this, we moved the call to special_symbol_handling out of the
+ loop in solib_add, so this only gets called once, rather than once
+ for every shared library, and also removed the call to lookup_minimal_symbol
+ in this routine. */
+
+static void
+solib_add_common_symbols (rtc_symp, objfile)
+ struct rt_symbol *rtc_symp;
+ struct objfile *objfile;
+{
+ struct rt_symbol inferior_rtc_symb;
+ struct nzlist inferior_rtc_nzlist;
+ int len;
+ char *name;
+ char *origname;
+
+ init_minimal_symbol_collection ();
+ make_cleanup (discard_minimal_symbols, 0);
+
+ while (rtc_symp)
+ {
+ read_memory ((CORE_ADDR) rtc_symp,
+ (char *) &inferior_rtc_symb,
+ sizeof (inferior_rtc_symb));
+ read_memory ((CORE_ADDR) inferior_rtc_symb.rt_sp,
+ (char *) &inferior_rtc_nzlist,
+ sizeof(inferior_rtc_nzlist));
+ if (inferior_rtc_nzlist.nz_type == N_COMM)
+ {
+ /* FIXME: The length of the symbol name is not available, but in the
+ current implementation the common symbol is allocated immediately
+ behind the name of the symbol. */
+ len = inferior_rtc_nzlist.nz_value - inferior_rtc_nzlist.nz_strx;
+
+ origname = name = xmalloc (len);
+ read_memory ((CORE_ADDR) inferior_rtc_nzlist.nz_name, name, len);
+
+ /* Don't enter the symbol twice if the target is re-run. */
+
+ if (name[0] == bfd_get_symbol_leading_char (objfile->obfd))
+ {
+ name++;
+ }
+
+#if 0
+ /* I think this is unnecessary, GDB can probably deal with
+ duplicate minimal symbols, more or less. And the duplication
+ which used to happen because this was called for each shared
+ library is gone now that we are just called once. */
+ /* FIXME: Do we really want to exclude symbols which happen
+ to match symbols for other locations in the inferior's
+ address space, even when they are in different linkage units? */
+ if (lookup_minimal_symbol (name, (struct objfile *) NULL) == NULL)
+#endif
+ {
+ name = obsavestring (name, strlen (name),
+ &objfile -> symbol_obstack);
+ prim_record_minimal_symbol (name, inferior_rtc_nzlist.nz_value,
+ mst_bss);
+ }
+ free (origname);
+ }
+ rtc_symp = inferior_rtc_symb.rt_next;
+ }
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+}
+
+#endif /* SVR4_SHARED_LIBS */
+
+#ifdef SVR4_SHARED_LIBS
+
+/*
+
+LOCAL FUNCTION
+
+ bfd_lookup_symbol -- lookup the value for a specific symbol
+
+SYNOPSIS
+
+ CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
+
+DESCRIPTION
+
+ An expensive way to lookup the value of a single symbol for
+ bfd's that are only temporary anyway. This is used by the
+ shared library support to find the address of the debugger
+ interface structures in the shared library.
+
+ Note that 0 is specifically allowed as an error return (no
+ such symbol).
+
+ FIXME: See if there is a less "expensive" way of doing this.
+ Also see if there is already another bfd or gdb function
+ that specifically does this, and if so, use it.
+*/
+
+static CORE_ADDR
+bfd_lookup_symbol (abfd, symname)
+ bfd *abfd;
+ char *symname;
+{
+ unsigned int storage_needed;
+ asymbol *sym;
+ asymbol **symbol_table;
+ unsigned int number_of_symbols;
+ unsigned int i;
+ struct cleanup *back_to;
+ CORE_ADDR symaddr = 0;
+
+ storage_needed = get_symtab_upper_bound (abfd);
+
+ if (storage_needed > 0)
+ {
+ symbol_table = (asymbol **) xmalloc (storage_needed);
+ back_to = make_cleanup (free, (PTR)symbol_table);
+ number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ sym = *symbol_table++;
+ if (STREQ (sym -> name, symname))
+ {
+ /* Bfd symbols are section relative. */
+ symaddr = sym -> value + sym -> section -> vma;
+ break;
+ }
+ }
+ do_cleanups (back_to);
+ }
+ return (symaddr);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ look_for_base -- examine file for each mapped address segment
+
+SYNOPSYS
+
+ static int look_for_base (int fd, CORE_ADDR baseaddr)
+
+DESCRIPTION
+
+ This function is passed to proc_iterate_over_mappings, which
+ causes it to get called once for each mapped address space, with
+ an open file descriptor for the file mapped to that space, and the
+ base address of that mapped space.
+
+ Our job is to find the symbol DEBUG_BASE in the file that this
+ fd is open on, if it exists, and if so, initialize the dynamic
+ linker structure base address debug_base.
+
+ Note that this is a computationally expensive proposition, since
+ we basically have to open a bfd on every call, so we specifically
+ avoid opening the exec file.
+ */
+
+static int
+look_for_base (fd, baseaddr)
+ int fd;
+ CORE_ADDR baseaddr;
+{
+ bfd *interp_bfd;
+ CORE_ADDR address;
+
+ /* If the fd is -1, then there is no file that corresponds to this
+ mapped memory segment, so skip it. Also, if the fd corresponds
+ to the exec file, skip it as well. */
+
+ if ((fd == -1) || fdmatch (fileno ((FILE *)(exec_bfd -> iostream)), fd))
+ {
+ return (0);
+ }
+
+ /* Try to open whatever random file this fd corresponds to. Note that
+ we have no way currently to find the filename. Don't gripe about
+ any problems we might have, just fail. */
+
+ if ((interp_bfd = bfd_fdopenr ("unnamed", gnutarget, fd)) == NULL)
+ {
+ return (0);
+ }
+ if (!bfd_check_format (interp_bfd, bfd_object))
+ {
+ bfd_close (interp_bfd);
+ return (0);
+ }
+
+ /* Now try to find our DEBUG_BASE symbol in this file, which we at
+ least know to be a valid ELF executable or shared library. */
+
+ if ((address = bfd_lookup_symbol (interp_bfd, DEBUG_BASE)) == 0)
+ {
+ bfd_close (interp_bfd);
+ return (0);
+ }
+
+ /* Eureka! We found the symbol. But now we may need to relocate it
+ by the base address. If the symbol's value is less than the base
+ address of the shared library, then it hasn't yet been relocated
+ by the dynamic linker, and we have to do it ourself. FIXME: Note
+ that we make the assumption that the first segment that corresponds
+ to the shared library has the base address to which the library
+ was relocated. */
+
+ if (address < baseaddr)
+ {
+ address += baseaddr;
+ }
+ debug_base = address;
+ bfd_close (interp_bfd);
+ return (1);
+}
+
+#endif
+
+/*
+
+LOCAL FUNCTION
+
+ locate_base -- locate the base address of dynamic linker structs
+
+SYNOPSIS
+
+ CORE_ADDR locate_base (void)
+
+DESCRIPTION
+
+ For both the SunOS and SVR4 shared library implementations, if the
+ inferior executable has been linked dynamically, there is a single
+ address somewhere in the inferior's data space which is the key to
+ locating all of the dynamic linker's runtime structures. This
+ address is the value of the symbol defined by the macro DEBUG_BASE.
+ The job of this function is to find and return that address, or to
+ return 0 if there is no such address (the executable is statically
+ linked for example).
+
+ For SunOS, the job is almost trivial, since the dynamic linker and
+ all of it's structures are statically linked to the executable at
+ link time. Thus the symbol for the address we are looking for has
+ already been added to the minimal symbol table for the executable's
+ objfile at the time the symbol file's symbols were read, and all we
+ have to do is look it up there. Note that we explicitly do NOT want
+ to find the copies in the shared library.
+
+ The SVR4 version is much more complicated because the dynamic linker
+ and it's structures are located in the shared C library, which gets
+ run as the executable's "interpreter" by the kernel. We have to go
+ to a lot more work to discover the address of DEBUG_BASE. Because
+ of this complexity, we cache the value we find and return that value
+ on subsequent invocations. Note there is no copy in the executable
+ symbol tables.
+
+ Note that we can assume nothing about the process state at the time
+ we need to find this address. We may be stopped on the first instruc-
+ tion of the interpreter (C shared library), the first instruction of
+ the executable itself, or somewhere else entirely (if we attached
+ to the process for example).
+
+ */
+
+static CORE_ADDR
+locate_base ()
+{
+
+#ifndef SVR4_SHARED_LIBS
+
+ struct minimal_symbol *msymbol;
+ CORE_ADDR address = 0;
+
+ /* For SunOS, we want to limit the search for DEBUG_BASE to the executable
+ being debugged, since there is a duplicate named symbol in the shared
+ library. We don't want the shared library versions. */
+
+ msymbol = lookup_minimal_symbol (DEBUG_BASE, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ address = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ return (address);
+
+#else /* SVR4_SHARED_LIBS */
+
+ /* Check to see if we have a currently valid address, and if so, avoid
+ doing all this work again and just return the cached address. If
+ we have no cached address, ask the /proc support interface to iterate
+ over the list of mapped address segments, calling look_for_base() for
+ each segment. When we are done, we will have either found the base
+ address or not. */
+
+ if (debug_base == 0)
+ {
+ proc_iterate_over_mappings (look_for_base);
+ }
+ return (debug_base);
+
+#endif /* !SVR4_SHARED_LIBS */
+
+}
+
+/*
+
+LOCAL FUNCTION
+
+ first_link_map_member -- locate first member in dynamic linker's map
+
+SYNOPSIS
+
+ static struct link_map *first_link_map_member (void)
+
+DESCRIPTION
+
+ Read in a copy of the first member in the inferior's dynamic
+ link map from the inferior's dynamic linker structures, and return
+ a pointer to the copy in our address space.
+*/
+
+#ifdef OLD_FreeBSD_LD
+static struct link_map *
+#else
+static struct so_map *
+#endif
+first_link_map_member ()
+{
+#ifdef OLD_FreeBSD_LD
+ struct link_map *lm = NULL;
+#else
+ struct so_map *lm = NULL;
+#endif
+
+#ifndef SVR4_SHARED_LIBS
+
+ read_memory (debug_base, (char *) &dynamic_copy, sizeof (dynamic_copy));
+#ifdef OLD_FreeBSD_LD
+ if (dynamic_copy.ld_version >= 2)
+ {
+ /* It is a version that we can deal with, so read in the secondary
+ structure and find the address of the link map list from it. */
+ read_memory ((CORE_ADDR) dynamic_copy.ld_un.ld_2, (char *) &ld_2_copy,
+ sizeof (struct link_dynamic_2));
+ lm = ld_2_copy.ld_loaded;
+ }
+#else
+ if (dynamic_copy.d_version >= 2)
+ {
+ /* It is a version that we can deal with, so read in the secondary
+ structure and find the address of the link map list from it. */
+ read_memory ((CORE_ADDR) dynamic_copy.d_un.d_sdt, (char *) &ld_2_copy,
+ sizeof (struct section_dispatch_table));
+ lm = ld_2_copy.sdt_loaded;
+ }
+#endif
+#else /* SVR4_SHARED_LIBS */
+
+ read_memory (debug_base, (char *) &debug_copy, sizeof (struct r_debug));
+ /* FIXME: Perhaps we should validate the info somehow, perhaps by
+ checking r_version for a known version number, or r_state for
+ RT_CONSISTENT. */
+ lm = debug_copy.r_map;
+
+#endif /* !SVR4_SHARED_LIBS */
+
+ return (lm);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ find_solib -- step through list of shared objects
+
+SYNOPSIS
+
+ struct so_list *find_solib (struct so_list *so_list_ptr)
+
+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>.
+ */
+
+static struct so_list *
+find_solib (so_list_ptr)
+ struct so_list *so_list_ptr; /* Last lm or NULL for first one */
+{
+ struct so_list *so_list_next = NULL;
+#ifdef OLD_FreeBSD_LD
+ struct link_map *lm = NULL;
+#else
+ struct so_map *lm = NULL;
+#endif
+ struct so_list *new;
+
+ if (so_list_ptr == NULL)
+ {
+ /* We are setting up for a new scan through the loaded images. */
+ if ((so_list_next = so_list_head) == NULL)
+ {
+ /* We have not already read in the dynamic linking structures
+ from the inferior, lookup the address of the base structure. */
+ debug_base = locate_base ();
+ if (debug_base != 0)
+ {
+ /* Read the base structure in and find the address of the first
+ link map list member. */
+ lm = first_link_map_member ();
+ }
+ }
+ }
+ else
+ {
+ /* We have been called before, and are in the process of walking
+ the shared library list. Advance to the next shared object. */
+ if ((lm = LM_NEXT (so_list_ptr)) == NULL)
+ {
+ /* We have hit the end of the list, so check to see if any were
+ added, but be quiet if we can't read from the target any more. */
+ int status = target_read_memory ((CORE_ADDR) so_list_ptr -> lmaddr,
+ (char *) &(so_list_ptr -> lm),
+#ifdef OLD_FreeBSD_LD
+ sizeof (struct link_map));
+#else
+ sizeof (struct so_map));
+#endif
+ if (status == 0)
+ {
+ lm = LM_NEXT (so_list_ptr);
+ }
+ else
+ {
+ lm = NULL;
+ }
+ }
+ so_list_next = so_list_ptr -> next;
+ }
+ if ((so_list_next == NULL) && (lm != NULL))
+ {
+ /* Get next link map structure from inferior image and build a local
+ abbreviated load_map structure */
+ new = (struct so_list *) xmalloc (sizeof (struct so_list));
+ memset ((char *) new, 0, sizeof (struct so_list));
+ new -> lmaddr = lm;
+ /* Add the new node as the next node in the list, or as the root
+ node if this is the first one. */
+ if (so_list_ptr != NULL)
+ {
+ so_list_ptr -> next = new;
+ }
+ else
+ {
+ so_list_head = new;
+ }
+ so_list_next = new;
+ read_memory ((CORE_ADDR) lm, (char *) &(new -> lm),
+#ifdef OLD_FreeBSD_LD
+ sizeof (struct link_map));
+#else
+ sizeof (struct so_map));
+#endif
+ /* For the SVR4 version, there is one entry that has no name
+ (for the inferior executable) since it is not a shared object. */
+ if (LM_NAME (new) != 0)
+ {
+ if (!target_read_string((CORE_ADDR) LM_NAME (new), new -> so_name,
+ MAX_PATH_SIZE - 1))
+ error ("find_solib: Can't read pathname for load map\n");
+ new -> so_name[MAX_PATH_SIZE - 1] = 0;
+ solib_map_sections (new);
+ }
+ }
+ return (so_list_next);
+}
+
+/* A small stub to get us past the arg-passing pinhole of catch_errors. */
+
+static int
+symbol_add_stub (arg)
+ char *arg;
+{
+ register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
+
+ so -> objfile = symbol_file_add (so -> so_name, so -> from_tty,
+ (unsigned int) so -> textsection -> addr,
+ 0, 0, 0);
+ return (1);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_add -- add a shared library file to the symtab and section list
+
+SYNOPSIS
+
+ void solib_add (char *arg_string, int from_tty,
+ struct target_ops *target)
+
+DESCRIPTION
+
+*/
+
+void
+solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ register struct so_list *so = NULL; /* link map state variable */
+
+ /* Last shared library that we read. */
+ struct so_list *so_last = NULL;
+
+ char *re_err;
+ int count;
+ int old;
+
+ if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
+ {
+ error ("Invalid regexp: %s", re_err);
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0] && re_exec (so -> so_name))
+ {
+ so -> from_tty = from_tty;
+ if (so -> symbols_loaded)
+ {
+ if (from_tty)
+ {
+ printf ("Symbols already loaded for %s\n", so -> so_name);
+ }
+ }
+ else if (catch_errors
+ (symbol_add_stub, (char *) so,
+ "Error while reading shared library symbols:\n",
+ RETURN_MASK_ALL))
+ {
+ so_last = so;
+ so -> symbols_loaded = 1;
+ }
+ }
+ }
+
+ /* Now add the shared library sections to the section table of the
+ specified target, if any. */
+ if (target)
+ {
+ /* Count how many new section_table entries there are. */
+ so = NULL;
+ count = 0;
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ count += so -> sections_end - so -> sections;
+ }
+ }
+
+ if (count)
+ {
+ /* Reallocate the target's section table including the new size. */
+ if (target -> to_sections)
+ {
+ old = target -> to_sections_end - target -> to_sections;
+ target -> to_sections = (struct section_table *)
+ xrealloc ((char *)target -> to_sections,
+ (sizeof (struct section_table)) * (count + old));
+ }
+ else
+ {
+ old = 0;
+ target -> to_sections = (struct section_table *)
+ xmalloc ((sizeof (struct section_table)) * count);
+ }
+ target -> to_sections_end = target -> to_sections + (count + old);
+
+ /* Add these section table entries to the target's table. */
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ count = so -> sections_end - so -> sections;
+ memcpy ((char *) (target -> to_sections + old),
+ so -> sections,
+ (sizeof (struct section_table)) * count);
+ old += count;
+ }
+ }
+ }
+ }
+
+ /* Calling this once at the end means that we put all the minimal
+ symbols for commons into the objfile for the last shared library.
+ Since they are in common, this should not be a problem. If we
+ delete the objfile with the minimal symbols, we can put all the
+ symbols into a new objfile (and will on the next call to solib_add).
+
+ An alternate approach would be to create an objfile just for
+ common minsyms, thus not needing any objfile argument to
+ solib_add_common_symbols. */
+
+ if (so_last)
+ special_symbol_handling (so_last);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ info_sharedlibrary_command -- code for "info sharedlibrary"
+
+SYNOPSIS
+
+ static void info_sharedlibrary_command ()
+
+DESCRIPTION
+
+ Walk through the shared library list and print information
+ about each attached library.
+*/
+
+static void
+info_sharedlibrary_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct so_list *so = NULL; /* link map state variable */
+ int header_done = 0;
+
+ if (exec_bfd == NULL)
+ {
+ printf ("No exec file.\n");
+ return;
+ }
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ if (!header_done)
+ {
+ printf("%-12s%-12s%-12s%s\n", "From", "To", "Syms Read",
+ "Shared Object Library");
+ header_done++;
+ }
+ printf ("%-12s",
+ local_hex_string_custom ((unsigned long) LM_ADDR (so),
+ "08l"));
+ printf ("%-12s",
+ local_hex_string_custom ((unsigned long) so -> lmend,
+ "08l"));
+ printf ("%-12s", so -> symbols_loaded ? "Yes" : "No");
+ printf ("%s\n", so -> so_name);
+ }
+ }
+ if (so_list_head == NULL)
+ {
+ printf ("No shared libraries loaded at this time.\n");
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_address -- check to see if an address is in a shared lib
+
+SYNOPSIS
+
+ int solib_address (CORE_ADDR address)
+
+DESCRIPTION
+
+ Provides a hook for other gdb routines to discover whether or
+ not a particular address is within the mapped address space of
+ a shared library. Any address between the base mapping address
+ and the first address beyond the end of the last mapping, is
+ considered to be within the shared library address space, for
+ our purposes.
+
+ For example, this routine is called at one point to disable
+ breakpoints which are in shared libraries that are not currently
+ mapped in.
+ */
+
+int
+solib_address (address)
+ CORE_ADDR address;
+{
+ register struct so_list *so = 0; /* link map state variable */
+
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ if ((address >= (CORE_ADDR) LM_ADDR (so)) &&
+ (address < (CORE_ADDR) so -> lmend))
+ {
+ return (1);
+ }
+ }
+ }
+ return (0);
+}
+
+/* Called by free_all_symtabs */
+
+void
+clear_solib()
+{
+ struct so_list *next;
+ char *bfd_filename;
+
+ while (so_list_head)
+ {
+ if (so_list_head -> sections)
+ {
+ free ((PTR)so_list_head -> sections);
+ }
+ if (so_list_head -> abfd)
+ {
+ bfd_filename = bfd_get_filename (so_list_head -> abfd);
+ bfd_close (so_list_head -> abfd);
+ }
+ else
+ /* This happens for the executable on SVR4. */
+ bfd_filename = NULL;
+
+ next = so_list_head -> next;
+ if (bfd_filename)
+ free ((PTR)bfd_filename);
+ free ((PTR)so_list_head);
+ so_list_head = next;
+ }
+ debug_base = 0;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ disable_break -- remove the "mapping changed" breakpoint
+
+SYNOPSIS
+
+ static int disable_break ()
+
+DESCRIPTION
+
+ Removes the breakpoint that gets hit when the dynamic linker
+ completes a mapping change.
+
+*/
+
+static int
+disable_break ()
+{
+ int status = 1;
+
+#ifndef SVR4_SHARED_LIBS
+
+ int in_debugger = 0;
+
+ /* Read the debugger structure from the inferior to retrieve the
+ address of the breakpoint and the original contents of the
+ breakpoint address. Remove the breakpoint by writing the original
+ contents back. */
+
+ read_memory (debug_addr, (char *) &debug_copy, sizeof (debug_copy));
+
+ /* Set `in_debugger' to zero now. */
+
+ write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger));
+
+#ifdef OLD_FreeBSD_LD
+ breakpoint_addr = (CORE_ADDR) debug_copy.ldd_bp_addr;
+ write_memory (breakpoint_addr, (char *) &debug_copy.ldd_bp_inst,
+ sizeof (debug_copy.ldd_bp_inst));
+#else
+ breakpoint_addr = (CORE_ADDR) debug_copy.dd_bpt_addr;
+ write_memory (breakpoint_addr, (char *) &debug_copy.dd_bpt_shadow,
+ sizeof (debug_copy.dd_bpt_shadow));
+#endif
+
+#else /* SVR4_SHARED_LIBS */
+
+ /* Note that breakpoint address and original contents are in our address
+ space, so we just need to write the original contents back. */
+
+ if (memory_remove_breakpoint (breakpoint_addr, shadow_contents) != 0)
+ {
+ status = 0;
+ }
+
+#endif /* !SVR4_SHARED_LIBS */
+
+ /* For the SVR4 version, we always know the breakpoint address. For the
+ SunOS version we don't know it until the above code is executed.
+ Grumble if we are stopped anywhere besides the breakpoint address. */
+
+ if (stop_pc != breakpoint_addr)
+ {
+ warning ("stopped at unknown breakpoint while handling shared libraries");
+ }
+
+ return (status);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ enable_break -- arrange for dynamic linker to hit breakpoint
+
+SYNOPSIS
+
+ int enable_break (void)
+
+DESCRIPTION
+
+ Both the SunOS and the SVR4 dynamic linkers have, as part of their
+ debugger interface, support for arranging for the inferior to hit
+ a breakpoint after mapping in the shared libraries. This function
+ enables that breakpoint.
+
+ For SunOS, there is a special flag location (in_debugger) which we
+ set to 1. When the dynamic linker sees this flag set, it will set
+ a breakpoint at a location known only to itself, after saving the
+ original contents of that place and the breakpoint address itself,
+ in it's own internal structures. When we resume the inferior, it
+ will eventually take a SIGTRAP when it runs into the breakpoint.
+ We handle this (in a different place) by restoring the contents of
+ the breakpointed location (which is only known after it stops),
+ chasing around to locate the shared libraries that have been
+ loaded, then resuming.
+
+ For SVR4, the debugger interface structure contains a member (r_brk)
+ which is statically initialized at the time the shared library is
+ built, to the offset of a function (_r_debug_state) which is guaran-
+ teed to be called once before mapping in a library, and again when
+ the mapping is complete. At the time we are examining this member,
+ it contains only the unrelocated offset of the function, so we have
+ to do our own relocation. Later, when the dynamic linker actually
+ runs, it relocates r_brk to be the actual address of _r_debug_state().
+
+ The debugger interface structure also contains an enumeration which
+ is set to either RT_ADD or RT_DELETE prior to changing the mapping,
+ depending upon whether or not the library is being mapped or unmapped,
+ and then set to RT_CONSISTENT after the library is mapped/unmapped.
+*/
+
+static int
+enable_break ()
+{
+ int success = 0;
+
+#ifndef SVR4_SHARED_LIBS
+
+ int j;
+ int in_debugger;
+
+ /* Get link_dynamic structure */
+
+ j = target_read_memory (debug_base, (char *) &dynamic_copy,
+ sizeof (dynamic_copy));
+ if (j)
+ {
+ /* unreadable */
+ return (0);
+ }
+
+ /* Calc address of debugger interface structure */
+
+#ifdef OLD_FreeBSD_LD
+ debug_addr = (CORE_ADDR) dynamic_copy.ldd;
+#else
+ debug_addr = (CORE_ADDR) dynamic_copy.d_debug;
+#endif
+
+ /* Calc address of `in_debugger' member of debugger interface structure */
+
+#ifdef OLD_FreeBSD_LD
+ flag_addr = debug_addr + (CORE_ADDR) ((char *) &debug_copy.ldd_in_debugger -
+ (char *) &debug_copy);
+#else
+ flag_addr = debug_addr + (CORE_ADDR) ((char *) &debug_copy.dd_in_debugger -
+ (char *) &debug_copy);
+#endif
+
+ /* Write a value of 1 to this member. */
+
+ in_debugger = 1;
+ write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger));
+ success = 1;
+
+#else /* SVR4_SHARED_LIBS */
+
+#ifdef BKPT_AT_SYMBOL
+
+ struct minimal_symbol *msymbol;
+ char **bkpt_namep;
+ CORE_ADDR bkpt_addr;
+
+ /* Scan through the list of symbols, trying to look up the symbol and
+ set a breakpoint there. Terminate loop when we/if we succeed. */
+
+ breakpoint_addr = 0;
+ for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
+ {
+ msymbol = lookup_minimal_symbol (*bkpt_namep, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ bkpt_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (target_insert_breakpoint (bkpt_addr, shadow_contents) == 0)
+ {
+ breakpoint_addr = bkpt_addr;
+ success = 1;
+ break;
+ }
+ }
+ }
+
+#else /* !BKPT_AT_SYMBOL */
+
+ struct symtab_and_line sal;
+
+ /* Read the debugger interface structure directly. */
+
+ read_memory (debug_base, (char *) &debug_copy, sizeof (debug_copy));
+
+ /* Set breakpoint at the debugger interface stub routine that will
+ be called just prior to each mapping change and again after the
+ mapping change is complete. Set up the (nonexistent) handler to
+ deal with hitting these breakpoints. (FIXME). */
+
+ warning ("'%s': line %d: missing SVR4 support code", __FILE__, __LINE__);
+ success = 1;
+
+#endif /* BKPT_AT_SYMBOL */
+
+#endif /* !SVR4_SHARED_LIBS */
+
+ return (success);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_create_inferior_hook -- shared library startup support
+
+SYNOPSIS
+
+ void solib_create_inferior_hook()
+
+DESCRIPTION
+
+ When gdb starts up the inferior, it nurses it along (through the
+ shell) until it is ready to execute it's first instruction. At this
+ point, this function gets called via expansion of the macro
+ SOLIB_CREATE_INFERIOR_HOOK.
+
+ For SunOS executables, this first instruction is typically the
+ one at "_start", or a similar text label, regardless of whether
+ the executable is statically or dynamically linked. The runtime
+ startup code takes care of dynamically linking in any shared
+ libraries, once gdb allows the inferior to continue.
+
+ For SVR4 executables, this first instruction is either the first
+ instruction in the dynamic linker (for dynamically linked
+ executables) or the instruction at "start" for statically linked
+ executables. For dynamically linked executables, the system
+ first exec's /lib/libc.so.N, which contains the dynamic linker,
+ and starts it running. The dynamic linker maps in any needed
+ shared libraries, maps in the actual user executable, and then
+ jumps to "start" in the user executable.
+
+ For both SunOS shared libraries, and SVR4 shared libraries, we
+ can arrange to cooperate with the dynamic linker to discover the
+ names of shared libraries that are dynamically linked, and the
+ base addresses to which they are linked.
+
+ This function is responsible for discovering those names and
+ addresses, and saving sufficient information about them to allow
+ their symbols to be read at a later time.
+
+FIXME
+
+ Between enable_break() and disable_break(), this code does not
+ properly handle hitting breakpoints which the user might have
+ set in the startup code or in the dynamic linker itself. Proper
+ handling will probably have to wait until the implementation is
+ changed to use the "breakpoint handler function" method.
+
+ Also, what if child has exit()ed? Must exit loop somehow.
+ */
+
+void
+solib_create_inferior_hook()
+{
+ /* If we are using the BKPT_AT_SYMBOL code, then we don't need the base
+ yet. In fact, in the case of a SunOS4 executable being run on
+ Solaris, we can't get it yet. find_solib will get it when it needs
+ it. */
+#if !(defined (SVR4_SHARED_LIBS) && defined (BKPT_AT_SYMBOL))
+ if ((debug_base = locate_base ()) == 0)
+ {
+ /* Can't find the symbol or the executable is statically linked. */
+ return;
+ }
+#endif
+
+ if (!enable_break ())
+ {
+ warning ("shared library handler failed to enable breakpoint");
+ return;
+ }
+
+ /* Now run the target. It will eventually hit the breakpoint, at
+ which point all of the libraries will have been mapped in and we
+ can go groveling around in the dynamic linker structures to find
+ out what we need to know about them. */
+
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ stop_signal = 0;
+ do
+ {
+ target_resume (-1, 0, stop_signal);
+ wait_for_inferior ();
+ }
+ while (stop_signal != SIGTRAP);
+ stop_soon_quietly = 0;
+
+ /* We are now either at the "mapping complete" breakpoint (or somewhere
+ else, a condition we aren't prepared to deal with anyway), so adjust
+ the PC as necessary after a breakpoint, disable the breakpoint, and
+ add any shared libraries that were mapped in. */
+
+ if (DECR_PC_AFTER_BREAK)
+ {
+ stop_pc -= DECR_PC_AFTER_BREAK;
+ write_register (PC_REGNUM, stop_pc);
+ }
+
+ if (!disable_break ())
+ {
+ warning ("shared library handler failed to disable breakpoint");
+ }
+
+ solib_add ((char *) 0, 0, (struct target_ops *) 0);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ special_symbol_handling -- additional shared library symbol handling
+
+SYNOPSIS
+
+ void special_symbol_handling (struct so_list *so)
+
+DESCRIPTION
+
+ Once the symbols from a shared object have been loaded in the usual
+ way, we are called to do any system specific symbol handling that
+ is needed.
+
+ For Suns, this consists of grunging around in the dynamic linkers
+ structures to find symbol definitions for "common" symbols and
+ adding them to the minimal symbol table for the corresponding
+ objfile.
+
+*/
+
+static void
+special_symbol_handling (so)
+struct so_list *so;
+{
+#ifndef SVR4_SHARED_LIBS
+ int j;
+
+ if (debug_addr == 0)
+ {
+ /* Get link_dynamic structure */
+
+ j = target_read_memory (debug_base, (char *) &dynamic_copy,
+ sizeof (dynamic_copy));
+ if (j)
+ {
+ /* unreadable */
+ return;
+ }
+
+ /* Calc address of debugger interface structure */
+ /* FIXME, this needs work for cross-debugging of core files
+ (byteorder, size, alignment, etc). */
+
+#ifdef OLD_FreeBSD_LD
+ debug_addr = (CORE_ADDR) dynamic_copy.ldd;
+#else
+ debug_addr = (CORE_ADDR) dynamic_copy.d_debug;
+#endif
+ }
+
+ /* Read the debugger structure from the inferior, just to make sure
+ we have a current copy. */
+
+ j = target_read_memory (debug_addr, (char *) &debug_copy,
+ sizeof (debug_copy));
+ if (j)
+ return; /* unreadable */
+
+ /* Get common symbol definitions for the loaded object. */
+
+#ifdef OLD_FreeBSD_LD
+ if (debug_copy.ldd_cp)
+ {
+ solib_add_common_symbols (debug_copy.ldd_cp, so -> objfile);
+ }
+#else
+ if (debug_copy.dd_cc)
+ {
+ solib_add_common_symbols (debug_copy.dd_cc, so -> objfile);
+ }
+#endif
+
+#endif /* !SVR4_SHARED_LIBS */
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ sharedlibrary_command -- handle command to explicitly add library
+
+SYNOPSIS
+
+ static void sharedlibrary_command (char *args, int from_tty)
+
+DESCRIPTION
+
+*/
+
+static void
+sharedlibrary_command (args, from_tty)
+char *args;
+int from_tty;
+{
+ dont_repeat ();
+ solib_add (args, from_tty, (struct target_ops *) 0);
+}
+
+void
+_initialize_solib()
+{
+
+ add_com ("sharedlibrary", class_files, sharedlibrary_command,
+ "Load shared object library symbols for files matching REGEXP.");
+ add_info ("sharedlibrary", info_sharedlibrary_command,
+ "Status of loaded shared object libraries.");
+}
diff --git a/gnu/usr.bin/gdb/gdb/gdb-stabs.h b/gnu/usr.bin/gdb/gdb/gdb-stabs.h
new file mode 100644
index 000000000000..c1e0253842ed
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/gdb-stabs.h
@@ -0,0 +1,76 @@
+/* Definitions for symbol-reading containing "stabs", for GDB.
+ Copyright 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by John Gilmore.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file exists to hold the common definitions required of most of
+ the symbol-readers that end up using stabs. The common use of
+ these `symbol-type-specific' customizations of the generic data
+ structures makes the stabs-oriented symbol readers able to call
+ each others' functions as required. */
+
+#if !defined (GDBSTABS_H)
+#define GDBSTABS_H
+
+/* Offsets in the psymtab's section_offsets array for various kinds of
+ stabs symbols. Every psymtab built from stabs will have these offsets
+ filled in by these guidelines, so that when actually reading symbols, the
+ proper offset can simply be selected and added to the symbol value. */
+
+#define SECT_OFF_TEXT 0
+#define SECT_OFF_DATA 1
+#define SECT_OFF_BSS 2
+#define SECT_OFF_RODATA 3
+#define SECT_OFF_MAX 4 /* Count of possible values */
+
+/* The stab_section_info chain remembers info from the ELF symbol table,
+ while psymtabs are being built for the other symbol tables in the
+ objfile. It is destroyed at the complation of psymtab-reading.
+ Any info that was used from it has been copied into psymtabs. */
+
+struct stab_section_info {
+ char *filename;
+ CORE_ADDR sections[SECT_OFF_MAX];
+ struct stab_section_info *next;
+ int found; /* Count of times it's found in searching */
+};
+
+/* Information is passed among various dbxread routines for accessing
+ symbol files. A pointer to this structure is kept in the sym_stab_info
+ field of the objfile struct. */
+
+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 */
+ file_ptr symtab_offset; /* Offset in file to symbol table */
+ int symbol_size; /* Bytes in a single symbol */
+ struct stab_section_info *stab_section_info; /* section starting points
+ of the original .o files before linking. */
+};
+
+#define DBX_SYMFILE_INFO(o) ((struct dbx_symfile_info *)((o)->sym_stab_info))
+#define DBX_TEXT_SECT(o) (DBX_SYMFILE_INFO(o)->text_sect)
+#define DBX_SYMCOUNT(o) (DBX_SYMFILE_INFO(o)->symcount)
+#define DBX_STRINGTAB(o) (DBX_SYMFILE_INFO(o)->stringtab)
+#define DBX_STRINGTAB_SIZE(o) (DBX_SYMFILE_INFO(o)->stringtab_size)
+#define DBX_SYMTAB_OFFSET(o) (DBX_SYMFILE_INFO(o)->symtab_offset)
+#define DBX_SYMBOL_SIZE(o) (DBX_SYMFILE_INFO(o)->symbol_size)
+
+#endif /* GDBSTABS_H */
diff --git a/gnu/usr.bin/gdb/gdb/gdb.1 b/gnu/usr.bin/gdb/gdb/gdb.1
new file mode 100644
index 000000000000..c6219de9c907
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/gdb.1
@@ -0,0 +1,371 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.\" $Id: gdb.1,v 1.1 1994/06/10 13:37:34 paul Exp $
+.TH gdb 1 "4nov1991" "GNU Tools" "GNU Tools"
+.SH NAME
+gdb \- The GNU Debugger
+.SH SYNOPSIS
+.na
+.TP
+.B gdb
+.RB "[\|" \-help "\|]"
+.RB "[\|" \-nx "\|]"
+.RB "[\|" \-q "\|]"
+.RB "[\|" \-batch "\|]"
+.RB "[\|" \-cd=\c
+.I dir\c
+\|]
+.RB "[\|" \-f "\|]"
+.RB "[\|" "\-b\ "\c
+.IR bps "\|]"
+.RB "[\|" "\-tty="\c
+.IR dev "\|]"
+.RB "[\|" "\-s "\c
+.I symfile\c
+\&\|]
+.RB "[\|" "\-e "\c
+.I prog\c
+\&\|]
+.RB "[\|" "\-se "\c
+.I prog\c
+\&\|]
+.RB "[\|" "\-c "\c
+.I core\c
+\&\|]
+.RB "[\|" "\-x "\c
+.I cmds\c
+\&\|]
+.RB "[\|" "\-d "\c
+.I dir\c
+\&\|]
+.RB "[\|" \c
+.I prog\c
+.RB "[\|" \c
+.IR core \||\| procID\c
+\&\|]\&\|]
+.ad b
+.SH DESCRIPTION
+The purpose of a debugger such as GDB is to allow you to see what is
+going on ``inside'' another program while it executes\(em\&or what another
+program was doing at the moment it crashed.
+
+GDB can do four main kinds of things (plus other things in support of
+these) to help you catch bugs in the act:
+
+.TP
+\ \ \ \(bu
+Start your program, specifying anything that might affect its behavior.
+
+.TP
+\ \ \ \(bu
+Make your program stop on specified conditions.
+
+.TP
+\ \ \ \(bu
+Examine what has happened, when your program has stopped.
+
+.TP
+\ \ \ \(bu
+Change things in your program, so you can experiment with correcting the
+effects of one bug and go on to learn about another.
+.PP
+
+You can use GDB to debug programs written in C, C++, and Modula-2.
+Fortran support will be added when a GNU Fortran compiler is ready.
+
+GDB is invoked with the shell command \c
+.B gdb\c
+\&. Once started, it reads
+commands from the terminal until you tell it to exit with the GDB
+command \c
+.B quit\c
+\&. You can get online help from \c
+.B gdb\c
+\& itself
+by using the command \c
+.B help\c
+\&.
+
+You can run \c
+.B gdb\c
+\& with no arguments or options; but the most
+usual way to start GDB is with one argument or two, specifying an
+executable program as the argument:
+.sp
+.br
+gdb\ program
+.br
+.sp
+
+You can also start with both an executable program and a core file specified:
+.sp
+.br
+gdb\ program\ core
+.br
+.sp
+
+You can, instead, specify a process ID as a second argument, if you want
+to debug a running process:
+.sp
+.br
+gdb\ program\ 1234
+.br
+.sp
+
+would attach GDB to process \c
+.B 1234\c
+\& (unless you also have a file
+named `\|\c
+.B 1234\c
+\&\|'; GDB does check for a core file first).
+
+Here are some of the most frequently needed GDB commands:
+.TP
+.B break \fR[\|\fIfile\fB:\fR\|]\fIfunction
+\&
+Set a breakpoint at \c
+.I function\c
+\& (in \c
+.I file\c
+\&).
+.TP
+.B run \fR[\|\fIarglist\fR\|]
+Start your program (with \c
+.I arglist\c
+\&, if specified).
+.TP
+.B bt
+Backtrace: display the program stack.
+.TP
+.BI print " expr"\c
+\&
+Display the value of an expression.
+.TP
+.B c
+Continue running your program (after stopping, e.g. at a breakpoint).
+.TP
+.B next
+Execute next program line (after stopping); step \c
+.I over\c
+\& any
+function calls in the line.
+.TP
+.B step
+Execute next program line (after stopping); step \c
+.I into\c
+\& any
+function calls in the line.
+.TP
+.B help \fR[\|\fIname\fR\|]
+Show information about GDB command \c
+.I name\c
+\&, or general information
+about using GDB.
+.TP
+.B quit
+Exit from GDB.
+.PP
+For full details on GDB, see \c
+.I
+Using GDB: A Guide to the GNU Source-Level Debugger\c
+\&, by Richard M. Stallman and Roland H. Pesch. The same text is available online
+as the \c
+.B gdb\c
+\& entry in the \c
+.B info\c
+\& program.
+.SH OPTIONS
+Any arguments other than options specify an executable
+file and core file (or process ID); that is, the first argument
+encountered with no
+associated option flag is equivalent to a `\|\c
+.B \-se\c
+\&\|' option, and the
+second, if any, is equivalent to a `\|\c
+.B \-c\c
+\&\|' option if it's the name of a file. Many options have
+both long and short forms; both are shown here. The long forms are also
+recognized if you truncate them, so long as enough of the option is
+present to be unambiguous. (If you prefer, you can flag option
+arguments with `\|\c
+.B +\c
+\&\|' rather than `\|\c
+.B \-\c
+\&\|', though we illustrate the
+more usual convention.)
+
+All the options and command line arguments you give are processed
+in sequential order. The order makes a difference when the
+`\|\c
+.B \-x\c
+\&\|' option is used.
+
+.TP
+.B \-help
+.TP
+.B \-h
+List all options, with brief explanations.
+
+.TP
+.BI "\-symbols=" "file"\c
+.TP
+.BI "\-s " "file"\c
+\&
+Read symbol table from file \c
+.I file\c
+\&.
+
+.TP
+.BI "\-exec=" "file"\c
+.TP
+.BI "\-e " "file"\c
+\&
+Use file \c
+.I file\c
+\& as the executable file to execute when
+appropriate, and for examining pure data in conjunction with a core
+dump.
+
+.TP
+.BI "\-se=" "file"\c
+\&
+Read symbol table from file \c
+.I file\c
+\& and use it as the executable
+file.
+
+.TP
+.BI "\-core=" "file"\c
+.TP
+.BI "\-c " "file"\c
+\&
+Use file \c
+.I file\c
+\& as a core dump to examine.
+
+.TP
+.BI "\-command=" "file"\c
+.TP
+.BI "\-x " "file"\c
+\&
+Execute GDB commands from file \c
+.I file\c
+\&.
+
+.TP
+.BI "\-directory=" "directory"\c
+.TP
+.BI "\-d " "directory"\c
+\&
+Add \c
+.I directory\c
+\& to the path to search for source files.
+.PP
+
+.TP
+.B \-nx
+.TP
+.B \-n
+Do not execute commands from any `\|\c
+.B .gdbinit\c
+\&\|' initialization files.
+Normally, the commands in these files are executed after all the
+command options and arguments have been processed.
+
+
+.TP
+.B \-quiet
+.TP
+.B \-q
+``Quiet''. Do not print the introductory and copyright messages. These
+messages are also suppressed in batch mode.
+
+.TP
+.B \-batch
+Run in batch mode. Exit with status \c
+.B 0\c
+\& after processing all the command
+files specified with `\|\c
+.B \-x\c
+\&\|' (and `\|\c
+.B .gdbinit\c
+\&\|', if not inhibited).
+Exit with nonzero status if an error occurs in executing the GDB
+commands in the command files.
+
+Batch mode may be useful for running GDB as a filter, for example to
+download and run a program on another computer; in order to make this
+more useful, the message
+.sp
+.br
+Program\ exited\ normally.
+.br
+.sp
+
+(which is ordinarily issued whenever a program running under GDB control
+terminates) is not issued when running in batch mode.
+
+.TP
+.BI "\-cd=" "directory"\c
+\&
+Run GDB using \c
+.I directory\c
+\& as its working directory,
+instead of the current directory.
+
+.TP
+.B \-fullname
+.TP
+.B \-f
+Emacs sets this option when it runs GDB as a subprocess. It tells GDB
+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 `\|\c
+.B \032\c
+\&\|' characters, followed by the file name, line number
+and character position separated by colons, and a newline. The
+Emacs-to-GDB interface program uses the two `\|\c
+.B \032\c
+\&\|' characters as
+a signal to display the source code for the frame.
+
+.TP
+.BI "\-b " "bps"\c
+\&
+Set the line speed (baud rate or bits per second) of any serial
+interface used by GDB for remote debugging.
+
+.TP
+.BI "\-tty=" "device"\c
+\&
+Run using \c
+.I device\c
+\& for your program's standard input and output.
+.PP
+
+.SH "SEE ALSO"
+.RB "`\|" gdb "\|'"
+entry in
+.B info\c
+\&;
+.I
+Using GDB: A Guide to the GNU Source-Level Debugger\c
+, Richard M. Stallman and Roland H. Pesch, July 1991.
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/gnu/usr.bin/gdb/gdb/gdbcmd.h b/gnu/usr.bin/gdb/gdb/gdbcmd.h
new file mode 100644
index 000000000000..88f323c73602
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/gdbcmd.h
@@ -0,0 +1,101 @@
+/* Header file for GDB-specific command-line stuff.
+ Copyright 1986, 1989, 1990, 1992 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (GDBCMD_H)
+#define GDBCMD_H 1
+
+#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 unset subcommands */
+
+extern struct cmd_list_element *unsetlist;
+
+/* 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;
+
+/* Chain containing all defined maintenance subcommands. */
+
+extern struct cmd_list_element *maintenancelist;
+
+/* Chain containing all defined "maintenance info" subcommands. */
+
+extern struct cmd_list_element *maintenanceinfolist;
+
+/* Chain containing all defined "maintenance print" subcommands. */
+
+extern struct cmd_list_element *maintenanceprintlist;
+
+extern struct cmd_list_element *setprintlist;
+
+extern struct cmd_list_element *showprintlist;
+
+extern struct cmd_list_element *setchecklist;
+
+extern struct cmd_list_element *showchecklist;
+
+extern void
+execute_user_command PARAMS ((struct cmd_list_element *, char *));
+
+extern void
+execute_command PARAMS ((char *, int));
+
+extern char **noop_completer PARAMS ((char *, char *));
+
+extern char **filename_completer PARAMS ((char *, char *));
+
+#endif /* !defined (GDBCMD_H) */
diff --git a/gnu/usr.bin/gdb/gdb/gdbcore.h b/gnu/usr.bin/gdb/gdb/gdbcore.h
new file mode 100644
index 000000000000..ec0f1b5a950a
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/gdbcore.h
@@ -0,0 +1,129 @@
+/* Machine independent variables that describe the core file under GDB.
+ Copyright 1986, 1987, 1989, 1990, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Interface routines for core, executable, etc. */
+
+#if !defined (GDBCORE_H)
+#define GDBCORE_H 1
+
+#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. */
+
+extern char *
+get_exec_file PARAMS ((int err));
+
+/* Nonzero if there is a core file. */
+
+extern int
+have_core_file_p PARAMS ((void));
+
+/* 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. */
+
+extern int
+read_memory_nobpt PARAMS ((CORE_ADDR memaddr, char *myaddr, unsigned len));
+
+/* Report a memory error with error(). */
+
+extern void
+memory_error PARAMS ((int status, CORE_ADDR memaddr));
+
+/* Like target_read_memory, but report an error if can't read. */
+
+extern void
+read_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+/* Read an integer from debugged memory, given address and number of bytes. */
+
+extern LONGEST
+read_memory_integer PARAMS ((CORE_ADDR memaddr, int len));
+
+/* Read an unsigned integer from debugged memory, given address and number of bytes. */
+
+extern unsigned LONGEST
+read_memory_unsigned_integer PARAMS ((CORE_ADDR memaddr, int len));
+
+/* If this is prototyped, need to deal with void* vs. char*. */
+
+extern void
+write_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) PARAMS ((char *filename));
+
+extern void
+specify_exec_file_hook PARAMS ((void (*hook) (char *filename)));
+
+/* Binary File Diddlers for the exec and core files */
+extern bfd *core_bfd;
+extern bfd *exec_bfd;
+
+/* Whether to open exec and core files read-only or read-write. */
+
+extern int write_files;
+
+extern void
+core_file_command PARAMS ((char *filename, int from_tty));
+
+extern void
+exec_file_command PARAMS ((char *filename, int from_tty));
+
+extern void
+validate_files PARAMS ((void));
+
+extern unsigned int
+register_addr PARAMS ((int regno, int blockend));
+
+extern int
+xfer_core_file PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+extern void
+fetch_core_registers PARAMS ((char *core_reg_sect, unsigned core_reg_size,
+ int which, unsigned int reg_addr));
+
+extern void
+registers_fetched PARAMS ((void));
+
+#if !defined (KERNEL_U_ADDR)
+extern CORE_ADDR kernel_u_addr;
+#define KERNEL_U_ADDR kernel_u_addr
+#endif
+
+/* The target vector for core files */
+extern struct target_ops core_ops;
+
+ /* target vector functions called directly from elsewhere */
+void
+core_open PARAMS ((char *, int));
+
+void
+core_detach PARAMS ((char *, int));
+
+/* The current default bfd target. */
+extern char *gnutarget;
+
+extern void set_gnutarget PARAMS ((char *));
+
+#endif /* !defined (GDBCORE_H) */
diff --git a/gnu/usr.bin/gdb/gdb/gdbtypes.c b/gnu/usr.bin/gdb/gdb/gdbtypes.c
new file mode 100644
index 000000000000..f34646935aa5
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/gdbtypes.c
@@ -0,0 +1,1440 @@
+/* Support routines for manipulating internal types for GDB.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <string.h>
+#include "bfd.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "language.h"
+#include "target.h"
+#include "value.h"
+#include "demangle.h"
+#include "complaints.h"
+
+/* 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;
+struct type *builtin_type_long_long;
+struct type *builtin_type_signed_char;
+struct type *builtin_type_unsigned_char;
+struct type *builtin_type_unsigned_short;
+struct type *builtin_type_unsigned_int;
+struct type *builtin_type_unsigned_long;
+struct type *builtin_type_unsigned_long_long;
+struct type *builtin_type_float;
+struct type *builtin_type_double;
+struct type *builtin_type_long_double;
+struct type *builtin_type_complex;
+struct type *builtin_type_double_complex;
+struct type *builtin_type_string;
+
+/* Alloc a new type structure and fill it with some defaults. If
+ OBJFILE is non-NULL, then allocate the space for the type structure
+ in that objfile's type_obstack. */
+
+struct type *
+alloc_type (objfile)
+ struct objfile *objfile;
+{
+ register struct type *type;
+
+ /* Alloc the structure and start off with all fields zeroed. */
+
+ if (objfile == NULL)
+ {
+ type = (struct type *) xmalloc (sizeof (struct type));
+ }
+ else
+ {
+ type = (struct type *) obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct type));
+ }
+ memset ((char *) type, 0, sizeof (struct type));
+
+ /* Initialize the fields that might not be zero. */
+
+ TYPE_CODE (type) = TYPE_CODE_UNDEF;
+ TYPE_OBJFILE (type) = objfile;
+ TYPE_VPTR_FIELDNO (type) = -1;
+
+ return (type);
+}
+
+/* Lookup a pointer to a type TYPE. TYPEPTR, if nonzero, points
+ to a pointer to memory where the pointer type should be stored.
+ If *TYPEPTR is zero, update it to point to the pointer type we return.
+ We allocate new memory if needed. */
+
+struct type *
+make_pointer_type (type, typeptr)
+ struct type *type;
+ struct type **typeptr;
+{
+ register struct type *ntype; /* New type */
+ struct objfile *objfile;
+
+ ntype = TYPE_POINTER_TYPE (type);
+
+ if (ntype)
+ if (typeptr == 0)
+ return ntype; /* Don't care about alloc, and have new type. */
+ else if (*typeptr == 0)
+ {
+ *typeptr = ntype; /* Tracking alloc, and we have new type. */
+ return ntype;
+ }
+
+ if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
+ {
+ ntype = alloc_type (TYPE_OBJFILE (type));
+ if (typeptr)
+ *typeptr = ntype;
+ }
+ else /* We have storage, but need to reset it. */
+ {
+ ntype = *typeptr;
+ objfile = TYPE_OBJFILE (ntype);
+ memset ((char *) ntype, 0, sizeof (struct type));
+ TYPE_OBJFILE (ntype) = objfile;
+ }
+
+ TYPE_TARGET_TYPE (ntype) = type;
+ TYPE_POINTER_TYPE (type) = ntype;
+
+ /* FIXME! Assume the machine has only one representation for pointers! */
+
+ TYPE_LENGTH (ntype) = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+ TYPE_CODE (ntype) = TYPE_CODE_PTR;
+
+ /* pointers are unsigned */
+ TYPE_FLAGS (ntype) |= TYPE_FLAG_UNSIGNED;
+
+ if (!TYPE_POINTER_TYPE (type)) /* Remember it, if don't have one. */
+ TYPE_POINTER_TYPE (type) = ntype;
+
+ return ntype;
+}
+
+/* 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. */
+
+struct type *
+lookup_pointer_type (type)
+ struct type *type;
+{
+ return make_pointer_type (type, (struct type **)0);
+}
+
+/* Lookup a C++ `reference' to a type TYPE. TYPEPTR, if nonzero, points
+ to a pointer to memory where the reference type should be stored.
+ If *TYPEPTR is zero, update it to point to the reference type we return.
+ We allocate new memory if needed. */
+
+struct type *
+make_reference_type (type, typeptr)
+ struct type *type;
+ struct type **typeptr;
+{
+ register struct type *ntype; /* New type */
+ struct objfile *objfile;
+
+ ntype = TYPE_REFERENCE_TYPE (type);
+
+ if (ntype)
+ if (typeptr == 0)
+ return ntype; /* Don't care about alloc, and have new type. */
+ else if (*typeptr == 0)
+ {
+ *typeptr = ntype; /* Tracking alloc, and we have new type. */
+ return ntype;
+ }
+
+ if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
+ {
+ ntype = alloc_type (TYPE_OBJFILE (type));
+ if (typeptr)
+ *typeptr = ntype;
+ }
+ else /* We have storage, but need to reset it. */
+ {
+ ntype = *typeptr;
+ objfile = TYPE_OBJFILE (ntype);
+ memset ((char *) ntype, 0, sizeof (struct type));
+ TYPE_OBJFILE (ntype) = objfile;
+ }
+
+ TYPE_TARGET_TYPE (ntype) = type;
+ TYPE_REFERENCE_TYPE (type) = ntype;
+
+ /* FIXME! Assume the machine has only one representation for references,
+ and that it matches the (only) representation for pointers! */
+
+ TYPE_LENGTH (ntype) = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+ TYPE_CODE (ntype) = TYPE_CODE_REF;
+
+ if (!TYPE_REFERENCE_TYPE (type)) /* Remember it, if don't have one. */
+ TYPE_REFERENCE_TYPE (type) = ntype;
+
+ return ntype;
+}
+
+/* Same as above, but caller doesn't care about memory allocation details. */
+
+struct type *
+lookup_reference_type (type)
+ struct type *type;
+{
+ return make_reference_type (type, (struct type **)0);
+}
+
+/* Lookup a function type that returns type TYPE. TYPEPTR, if nonzero, points
+ to a pointer to memory where the function type should be stored.
+ If *TYPEPTR is zero, update it to point to the function type we return.
+ We allocate new memory if needed. */
+
+struct type *
+make_function_type (type, typeptr)
+ struct type *type;
+ struct type **typeptr;
+{
+ register struct type *ntype; /* New type */
+ struct objfile *objfile;
+
+ ntype = TYPE_FUNCTION_TYPE (type);
+
+ if (ntype)
+ if (typeptr == 0)
+ return ntype; /* Don't care about alloc, and have new type. */
+ else if (*typeptr == 0)
+ {
+ *typeptr = ntype; /* Tracking alloc, and we have new type. */
+ return ntype;
+ }
+
+ if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
+ {
+ ntype = alloc_type (TYPE_OBJFILE (type));
+ if (typeptr)
+ *typeptr = ntype;
+ }
+ else /* We have storage, but need to reset it. */
+ {
+ ntype = *typeptr;
+ objfile = TYPE_OBJFILE (ntype);
+ memset ((char *) ntype, 0, sizeof (struct type));
+ TYPE_OBJFILE (ntype) = objfile;
+ }
+
+ TYPE_TARGET_TYPE (ntype) = type;
+ TYPE_FUNCTION_TYPE (type) = ntype;
+
+ TYPE_LENGTH (ntype) = 1;
+ TYPE_CODE (ntype) = TYPE_CODE_FUNC;
+
+ if (!TYPE_FUNCTION_TYPE (type)) /* Remember it, if don't have one. */
+ TYPE_FUNCTION_TYPE (type) = ntype;
+
+ return ntype;
+}
+
+
+/* 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;
+{
+ return make_function_type (type, (struct type **)0);
+}
+
+/* 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;
+ struct type *domain;
+{
+ register struct type *mtype;
+
+ mtype = alloc_type (TYPE_OBJFILE (type));
+ smash_to_member_type (mtype, domain, type);
+ return (mtype);
+}
+
+/* Allocate a stub method whose return type is TYPE.
+ This apparently happens for speed of symbol reading, since parsing
+ out the arguments to the method is cpu-intensive, the way we are doing
+ it. So, we will fill in arguments later.
+ This always returns a fresh type. */
+
+struct type *
+allocate_stub_method (type)
+ struct type *type;
+{
+ struct type *mtype;
+
+ mtype = alloc_type (TYPE_OBJFILE (type));
+ TYPE_TARGET_TYPE (mtype) = type;
+ /* _DOMAIN_TYPE (mtype) = unknown yet */
+ /* _ARG_TYPES (mtype) = unknown yet */
+ TYPE_FLAGS (mtype) = TYPE_FLAG_STUB;
+ TYPE_CODE (mtype) = TYPE_CODE_METHOD;
+ TYPE_LENGTH (mtype) = 1;
+ return (mtype);
+}
+
+/* Create a range type using either a blank type supplied in RESULT_TYPE,
+ or creating a new type, inheriting the objfile from INDEX_TYPE.
+
+ Indices will be of type INDEX_TYPE, and will range from LOW_BOUND to
+ HIGH_BOUND, inclusive.
+
+ FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
+ sure it is TYPE_CODE_UNDEF before we bash it into a range type? */
+
+struct type *
+create_range_type (result_type, index_type, low_bound, high_bound)
+ struct type *result_type;
+ struct type *index_type;
+ int low_bound;
+ int high_bound;
+{
+ if (result_type == NULL)
+ {
+ result_type = alloc_type (TYPE_OBJFILE (index_type));
+ }
+ TYPE_CODE (result_type) = TYPE_CODE_RANGE;
+ TYPE_TARGET_TYPE (result_type) = index_type;
+ TYPE_LENGTH (result_type) = TYPE_LENGTH (index_type);
+ TYPE_NFIELDS (result_type) = 2;
+ TYPE_FIELDS (result_type) = (struct field *)
+ TYPE_ALLOC (result_type, 2 * sizeof (struct field));
+ memset (TYPE_FIELDS (result_type), 0, 2 * sizeof (struct field));
+ TYPE_FIELD_BITPOS (result_type, 0) = low_bound;
+ TYPE_FIELD_BITPOS (result_type, 1) = high_bound;
+ TYPE_FIELD_TYPE (result_type, 0) = builtin_type_int; /* FIXME */
+ TYPE_FIELD_TYPE (result_type, 1) = builtin_type_int; /* FIXME */
+
+ return (result_type);
+}
+
+
+/* Create an array type using either a blank type supplied in RESULT_TYPE,
+ or creating a new type, inheriting the objfile from RANGE_TYPE.
+
+ Elements will be of type ELEMENT_TYPE, the indices will be of type
+ RANGE_TYPE.
+
+ FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
+ sure it is TYPE_CODE_UNDEF before we bash it into an array type? */
+
+struct type *
+create_array_type (result_type, element_type, range_type)
+ struct type *result_type;
+ struct type *element_type;
+ struct type *range_type;
+{
+ int low_bound;
+ int high_bound;
+
+ if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
+ {
+ /* FIXME: We only handle range types at the moment. Complain and
+ create a dummy range type to use. */
+ warning ("internal error: array index type must be a range type");
+ range_type = lookup_fundamental_type (TYPE_OBJFILE (range_type),
+ FT_INTEGER);
+ range_type = create_range_type ((struct type *) NULL, range_type, 0, 0);
+ }
+ if (result_type == NULL)
+ {
+ result_type = alloc_type (TYPE_OBJFILE (range_type));
+ }
+ TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
+ TYPE_TARGET_TYPE (result_type) = element_type;
+ low_bound = TYPE_FIELD_BITPOS (range_type, 0);
+ high_bound = TYPE_FIELD_BITPOS (range_type, 1);
+ TYPE_LENGTH (result_type) =
+ TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+ TYPE_NFIELDS (result_type) = 1;
+ TYPE_FIELDS (result_type) =
+ (struct field *) TYPE_ALLOC (result_type, sizeof (struct field));
+ memset (TYPE_FIELDS (result_type), 0, sizeof (struct field));
+ TYPE_FIELD_TYPE (result_type, 0) = range_type;
+ TYPE_VPTR_FIELDNO (result_type) = -1;
+
+ return (result_type);
+}
+
+/* Create a string type using either a blank type supplied in RESULT_TYPE,
+ or creating a new type. String types are similar enough to array of
+ char types that we can use create_array_type to build the basic type
+ and then bash it into a string type.
+
+ For fixed length strings, the range type contains 0 as the lower
+ bound and the length of the string minus one as the upper bound.
+
+ FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
+ sure it is TYPE_CODE_UNDEF before we bash it into a string type? */
+
+struct type *
+create_string_type (result_type, range_type)
+ struct type *result_type;
+ struct type *range_type;
+{
+ result_type = create_array_type (result_type, builtin_type_char, range_type);
+ TYPE_CODE (result_type) = TYPE_CODE_STRING;
+ return (result_type);
+}
+
+/* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE.
+ A MEMBER is a wierd thing -- it amounts to a typed offset into
+ a struct, e.g. "an int at offset 8". A MEMBER TYPE doesn't
+ include the offset (that's the value of the MEMBER itself), but does
+ include the structure type into which it points (for some reason).
+
+ When "smashing" the type, we preserve the objfile that the
+ old type pointed to, since we aren't changing where the type is actually
+ allocated. */
+
+void
+smash_to_member_type (type, domain, to_type)
+ struct type *type;
+ struct type *domain;
+ struct type *to_type;
+{
+ struct objfile *objfile;
+
+ objfile = TYPE_OBJFILE (type);
+
+ memset ((char *) type, 0, sizeof (struct type));
+ TYPE_OBJFILE (type) = objfile;
+ TYPE_TARGET_TYPE (type) = to_type;
+ TYPE_DOMAIN_TYPE (type) = domain;
+ TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
+ TYPE_CODE (type) = TYPE_CODE_MEMBER;
+}
+
+/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE.
+ METHOD just means `function that gets an extra "this" argument'.
+
+ When "smashing" the type, we preserve the objfile that the
+ old type pointed to, since we aren't changing where the type is actually
+ allocated. */
+
+void
+smash_to_method_type (type, domain, to_type, args)
+ struct type *type;
+ struct type *domain;
+ struct type *to_type;
+ struct type **args;
+{
+ struct objfile *objfile;
+
+ objfile = TYPE_OBJFILE (type);
+
+ memset ((char *) type, 0, sizeof (struct type));
+ TYPE_OBJFILE (type) = objfile;
+ TYPE_TARGET_TYPE (type) = to_type;
+ TYPE_DOMAIN_TYPE (type) = domain;
+ TYPE_ARG_TYPES (type) = args;
+ TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
+ TYPE_CODE (type) = TYPE_CODE_METHOD;
+}
+
+/* Return a typename for a struct/union/enum type without "struct ",
+ "union ", or "enum ". If the type has a NULL name, return NULL. */
+
+char *
+type_name_no_tag (type)
+ register const struct type *type;
+{
+ if (TYPE_TAG_NAME (type) != NULL)
+ return TYPE_TAG_NAME (type);
+
+ /* Is there code which expects this to return the name if there is no
+ tag name? My guess is that this is mainly used for C++ in cases where
+ the two will always be the same. */
+ return TYPE_NAME (type);
+}
+
+/* Lookup a primitive type named NAME.
+ Return zero if NAME is not a primitive type.*/
+
+struct type *
+lookup_primitive_typename (name)
+ char *name;
+{
+ struct type ** const *p;
+
+ for (p = current_language -> la_builtin_type_vector; *p != NULL; p++)
+ {
+ if (STREQ ((**p) -> name, name))
+ {
+ return (**p);
+ }
+ }
+ return (NULL);
+}
+
+/* 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;
+ register struct type *tmp;
+
+ sym = lookup_symbol (name, block, VAR_NAMESPACE, 0, (struct symtab **) NULL);
+ if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+ {
+ tmp = lookup_primitive_typename (name);
+ if (tmp)
+ {
+ return (tmp);
+ }
+ else if (!tmp && noerr)
+ {
+ return (NULL);
+ }
+ else
+ {
+ error ("No type named %s.", name);
+ }
+ }
+ return (SYMBOL_TYPE (sym));
+}
+
+struct type *
+lookup_unsigned_typename (name)
+ char *name;
+{
+ char *uns = alloca (strlen (name) + 10);
+
+ strcpy (uns, "unsigned ");
+ strcpy (uns + 9, name);
+ return (lookup_typename (uns, (struct block *) NULL, 0));
+}
+
+struct type *
+lookup_signed_typename (name)
+ char *name;
+{
+ struct type *t;
+ char *uns = alloca (strlen (name) + 8);
+
+ strcpy (uns, "signed ");
+ strcpy (uns + 7, name);
+ t = lookup_typename (uns, (struct block *) NULL, 1);
+ /* If we don't find "signed FOO" just try again with plain "FOO". */
+ if (t != NULL)
+ return t;
+ return lookup_typename (name, (struct block *) NULL, 0);
+}
+
+/* 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;
+
+ sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+
+ if (sym == NULL)
+ {
+ 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;
+
+ sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+
+ if (sym == NULL)
+ {
+ 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;
+
+ sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+ if (sym == NULL)
+ {
+ 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));
+}
+
+/* Lookup a template type named "template NAME<TYPE>",
+ visible in lexical block BLOCK. */
+
+struct type *
+lookup_template_type (name, type, block)
+ char *name;
+ struct type *type;
+ struct block *block;
+{
+ struct symbol *sym;
+ char *nam = (char*) alloca(strlen(name) + strlen(type->name) + 4);
+ strcpy (nam, name);
+ strcat (nam, "<");
+ strcat (nam, type->name);
+ strcat (nam, " >"); /* FIXME, extra space still introduced in gcc? */
+
+ sym = lookup_symbol (nam, block, VAR_NAMESPACE, 0, (struct symtab **)NULL);
+
+ if (sym == NULL)
+ {
+ error ("No template 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));
+}
+
+/* Given a type TYPE, lookup the type of the component of type named NAME.
+
+ TYPE can be either a struct or union, or a pointer or reference to a struct or
+ union. If it is a pointer or reference, its target type is automatically used.
+ Thus '.' and '->' are interchangable, as specified for the definitions of the
+ expression element types STRUCTOP_STRUCT and STRUCTOP_PTR.
+
+ If NOERR is nonzero, return zero if NAME is not suitably defined.
+ If NAME is the name of a baseclass type, return that type. */
+
+struct type *
+lookup_struct_elt_type (type, name, noerr)
+ struct type *type;
+ char *name;
+ int noerr;
+{
+ int i;
+
+ if (TYPE_CODE (type) == TYPE_CODE_PTR ||
+ TYPE_CODE (type) == TYPE_CODE_REF)
+ type = TYPE_TARGET_TYPE (type);
+
+ 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.");
+ }
+
+ check_stub_type (type);
+
+#if 0
+ /* FIXME: This change put in by Michael seems incorrect for the case where
+ the structure tag name is the same as the member name. I.E. when doing
+ "ptype bell->bar" for "struct foo { int bar; int foo; } bell;"
+ Disabled by fnf. */
+ {
+ char *typename;
+
+ typename = type_name_no_tag (type);
+ if (typename != NULL && STREQ (typename, name))
+ return type;
+ }
+#endif
+
+ 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 && STREQ (t_field_name, name))
+ {
+ return TYPE_FIELD_TYPE (type, i);
+ }
+ }
+
+ /* OK, it's not in this class. Recursively check the baseclasses. */
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ struct type *t;
+
+ t = lookup_struct_elt_type (TYPE_BASECLASS (type, i), name, noerr);
+ if (t != NULL)
+ {
+ return t;
+ }
+ }
+
+ if (noerr)
+ {
+ return NULL;
+ }
+
+ 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 */
+}
+
+/* If possible, make the vptr_fieldno and vptr_basetype fields of TYPE
+ valid. Callers should be aware that in some cases (for example,
+ the type or one of its baseclasses is a stub type and we are
+ debugging a .o file), this function will not be able to find the virtual
+ function table pointer, and vptr_fieldno will remain -1 and vptr_basetype
+ will remain NULL. */
+
+void
+fill_in_vptr_fieldno (type)
+ struct type *type;
+{
+ check_stub_type (type);
+
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ {
+ int i;
+
+ /* We must start at zero in case the first (and only) baseclass is
+ virtual (and hence we cannot share the table pointer). */
+ for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+ {
+ fill_in_vptr_fieldno (TYPE_BASECLASS (type, i));
+ if (TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, i)) >= 0)
+ {
+ TYPE_VPTR_FIELDNO (type)
+ = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, i));
+ TYPE_VPTR_BASETYPE (type)
+ = TYPE_VPTR_BASETYPE (TYPE_BASECLASS (type, i));
+ break;
+ }
+ }
+ }
+}
+
+/* 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. (FIXME, this doesn't seem
+ to be happening...)
+
+ 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);
+ /* FIXME: shouldn't we separately check the TYPE_NAME and the
+ TYPE_TAG_NAME, and look in STRUCT_NAMESPACE and/or VAR_NAMESPACE
+ as appropriate? (this code was written before TYPE_NAME and
+ TYPE_TAG_NAME were separate). */
+ struct symbol *sym;
+ if (name == NULL)
+ {
+ complain (&stub_noname_complaint);
+ return;
+ }
+ sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+ if (sym)
+ {
+ memcpy ((char *)type, (char *)SYMBOL_TYPE(sym), sizeof (struct type));
+ }
+ }
+}
+
+/* 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;
+ int j;
+{
+ struct fn_field *f;
+ char *mangled_name = gdb_mangle_name (type, i, j);
+ char *demangled_name = cplus_demangle (mangled_name,
+ DMGL_PARAMS | DMGL_ANSI);
+ char *argtypetext, *p;
+ int depth = 0, argcount = 1;
+ struct type **argtypes;
+ struct type *mtype;
+
+ if (demangled_name == NULL)
+ {
+ error ("Internal: Cannot demangle mangled name `%s'.", mangled_name);
+ }
+
+ /* 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 two more slots: one for the THIS pointer, and one for the
+ NULL [...] or void [end of arglist]. */
+
+ argtypes = (struct type **)
+ TYPE_ALLOC (type, (argcount + 2) * sizeof (struct type *));
+ p = argtypetext;
+ argtypes[0] = lookup_pointer_type (type);
+ argcount = 1;
+
+ if (*p != ')') /* () means no args, skip while */
+ {
+ depth = 0;
+ while (*p)
+ {
+ if (depth <= 0 && (*p == ',' || *p == ')'))
+ {
+ argtypes[argcount] =
+ parse_and_eval_type (argtypetext, p - argtypetext);
+ argcount += 1;
+ argtypetext = p + 1;
+ }
+
+ if (*p == '(')
+ {
+ depth += 1;
+ }
+ else if (*p == ')')
+ {
+ depth -= 1;
+ }
+
+ p += 1;
+ }
+ }
+
+ if (p[-2] != '.') /* Not '...' */
+ {
+ argtypes[argcount] = builtin_type_void; /* List terminator */
+ }
+ else
+ {
+ argtypes[argcount] = NULL; /* Ellist terminator */
+ }
+
+ free (demangled_name);
+
+ f = TYPE_FN_FIELDLIST1 (type, i);
+ TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
+
+ /* Now update the old "stub" type into a real type. */
+ mtype = TYPE_FN_FIELD_TYPE (f, j);
+ TYPE_DOMAIN_TYPE (mtype) = type;
+ TYPE_ARG_TYPES (mtype) = argtypes;
+ TYPE_FLAGS (mtype) &= ~TYPE_FLAG_STUB;
+ TYPE_FN_FIELD_STUB (f, j) = 0;
+}
+
+const struct cplus_struct_type cplus_struct_default;
+
+void
+allocate_cplus_struct_type (type)
+ struct type *type;
+{
+ if (!HAVE_CPLUS_STRUCT (type))
+ {
+ TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
+ TYPE_ALLOC (type, sizeof (struct cplus_struct_type));
+ *(TYPE_CPLUS_SPECIFIC(type)) = cplus_struct_default;
+ }
+}
+
+/* Helper function to initialize the standard scalar types.
+
+ If NAME is non-NULL and OBJFILE is non-NULL, then we make a copy
+ of the string pointed to by name in the type_obstack for that objfile,
+ and initialize the type name to that copy. There are places (mipsread.c
+ in particular, where init_type is called with a NULL value for NAME). */
+
+struct type *
+init_type (code, length, flags, name, objfile)
+ enum type_code code;
+ int length;
+ int flags;
+ char *name;
+ struct objfile *objfile;
+{
+ register struct type *type;
+
+ type = alloc_type (objfile);
+ TYPE_CODE (type) = code;
+ TYPE_LENGTH (type) = length;
+ TYPE_FLAGS (type) |= flags;
+ if ((name != NULL) && (objfile != NULL))
+ {
+ TYPE_NAME (type) =
+ obsavestring (name, strlen (name), &objfile -> type_obstack);
+ }
+ else
+ {
+ TYPE_NAME (type) = name;
+ }
+
+ /* C++ fancies. */
+
+ if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
+ {
+ INIT_CPLUS_SPECIFIC (type);
+ }
+ return (type);
+}
+
+/* Look up a fundamental type for the specified objfile.
+ May need to construct such a type if this is the first use.
+
+ Some object file formats (ELF, COFF, etc) do not define fundamental
+ types such as "int" or "double". Others (stabs for example), do
+ define fundamental types.
+
+ For the formats which don't provide fundamental types, gdb can create
+ such types, using defaults reasonable for the current language and
+ the current target machine.
+
+ NOTE: This routine is obsolescent. Each debugging format reader
+ should manage it's own fundamental types, either creating them from
+ suitable defaults or reading them from the debugging information,
+ whichever is appropriate. The DWARF reader has already been
+ fixed to do this. Once the other readers are fixed, this routine
+ will go away. Also note that fundamental types should be managed
+ on a compilation unit basis in a multi-language environment, not
+ on a linkage unit basis as is done here. */
+
+
+struct type *
+lookup_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type **typep;
+ register int nbytes;
+
+ if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
+ {
+ error ("internal error - invalid fundamental type id %d", typeid);
+ }
+
+ /* If this is the first time we need a fundamental type for this objfile
+ then we need to initialize the vector of type pointers. */
+
+ if (objfile -> fundamental_types == NULL)
+ {
+ nbytes = FT_NUM_MEMBERS * sizeof (struct type *);
+ objfile -> fundamental_types = (struct type **)
+ obstack_alloc (&objfile -> type_obstack, nbytes);
+ memset ((char *) objfile -> fundamental_types, 0, nbytes);
+ }
+
+ /* Look for this particular type in the fundamental type vector. If one is
+ not found, create and install one appropriate for the current language. */
+
+ typep = objfile -> fundamental_types + typeid;
+ if (*typep == NULL)
+ {
+ *typep = create_fundamental_type (objfile, typeid);
+ }
+
+ return (*typep);
+}
+
+#if MAINTENANCE_CMDS
+
+static void
+print_bit_vector (bits, nbits)
+ B_TYPE *bits;
+ int nbits;
+{
+ int bitno;
+
+ for (bitno = 0; bitno < nbits; bitno++)
+ {
+ if ((bitno % 8) == 0)
+ {
+ puts_filtered (" ");
+ }
+ if (B_TST (bits, bitno))
+ {
+ printf_filtered ("1");
+ }
+ else
+ {
+ printf_filtered ("0");
+ }
+ }
+}
+
+/* The args list is a strange beast. It is either terminated by a NULL
+ pointer for varargs functions, or by a pointer to a TYPE_CODE_VOID
+ type for normal fixed argcount functions. (FIXME someday)
+ Also note the first arg should be the "this" pointer, we may not want to
+ include it since we may get into a infinitely recursive situation. */
+
+static void
+print_arg_types (args, spaces)
+ struct type **args;
+ int spaces;
+{
+ if (args != NULL)
+ {
+ while (*args != NULL)
+ {
+ recursive_dump_type (*args, spaces + 2);
+ if ((*args++) -> code == TYPE_CODE_VOID)
+ {
+ break;
+ }
+ }
+ }
+}
+
+static void
+dump_fn_fieldlists (type, spaces)
+ struct type *type;
+ int spaces;
+{
+ int method_idx;
+ int overload_idx;
+ struct fn_field *f;
+
+ printfi_filtered (spaces, "fn_fieldlists 0x%lx\n",
+ (unsigned long) TYPE_FN_FIELDLISTS (type));
+ for (method_idx = 0; method_idx < TYPE_NFN_FIELDS (type); method_idx++)
+ {
+ f = TYPE_FN_FIELDLIST1 (type, method_idx);
+ printfi_filtered (spaces + 2, "[%d] name '%s' (0x%lx) length %d\n",
+ method_idx,
+ TYPE_FN_FIELDLIST_NAME (type, method_idx),
+ (unsigned long) TYPE_FN_FIELDLIST_NAME (type, method_idx),
+ TYPE_FN_FIELDLIST_LENGTH (type, method_idx));
+ for (overload_idx = 0;
+ overload_idx < TYPE_FN_FIELDLIST_LENGTH (type, method_idx);
+ overload_idx++)
+ {
+ printfi_filtered (spaces + 4, "[%d] physname '%s' (0x%lx)\n",
+ overload_idx,
+ TYPE_FN_FIELD_PHYSNAME (f, overload_idx),
+ (unsigned long) TYPE_FN_FIELD_PHYSNAME (f, overload_idx));
+ printfi_filtered (spaces + 8, "type 0x%lx\n",
+ (unsigned long) TYPE_FN_FIELD_TYPE (f, overload_idx));
+ recursive_dump_type (TYPE_FN_FIELD_TYPE (f, overload_idx),
+ spaces + 8 + 2);
+ printfi_filtered (spaces + 8, "args 0x%lx\n",
+ (unsigned long) TYPE_FN_FIELD_ARGS (f, overload_idx));
+ print_arg_types (TYPE_FN_FIELD_ARGS (f, overload_idx), spaces);
+ printfi_filtered (spaces + 8, "fcontext 0x%lx\n",
+ (unsigned long) TYPE_FN_FIELD_FCONTEXT (f, overload_idx));
+ printfi_filtered (spaces + 8, "is_const %d\n",
+ TYPE_FN_FIELD_CONST (f, overload_idx));
+ printfi_filtered (spaces + 8, "is_volatile %d\n",
+ TYPE_FN_FIELD_VOLATILE (f, overload_idx));
+ printfi_filtered (spaces + 8, "is_private %d\n",
+ TYPE_FN_FIELD_PRIVATE (f, overload_idx));
+ printfi_filtered (spaces + 8, "is_protected %d\n",
+ TYPE_FN_FIELD_PROTECTED (f, overload_idx));
+ printfi_filtered (spaces + 8, "is_stub %d\n",
+ TYPE_FN_FIELD_STUB (f, overload_idx));
+ printfi_filtered (spaces + 8, "voffset %u\n",
+ TYPE_FN_FIELD_VOFFSET (f, overload_idx));
+ }
+ }
+}
+
+static void
+print_cplus_stuff (type, spaces)
+ struct type *type;
+ int spaces;
+{
+ printfi_filtered (spaces, "n_baseclasses %d\n",
+ TYPE_N_BASECLASSES (type));
+ printfi_filtered (spaces, "nfn_fields %d\n",
+ TYPE_NFN_FIELDS (type));
+ printfi_filtered (spaces, "nfn_fields_total %d\n",
+ TYPE_NFN_FIELDS_TOTAL (type));
+ if (TYPE_N_BASECLASSES (type) > 0)
+ {
+ printfi_filtered (spaces, "virtual_field_bits (%d bits at *0x%lx)",
+ TYPE_N_BASECLASSES (type),
+ (unsigned long) TYPE_FIELD_VIRTUAL_BITS (type));
+ print_bit_vector (TYPE_FIELD_VIRTUAL_BITS (type),
+ TYPE_N_BASECLASSES (type));
+ puts_filtered ("\n");
+ }
+ if (TYPE_NFIELDS (type) > 0)
+ {
+ if (TYPE_FIELD_PRIVATE_BITS (type) != NULL)
+ {
+ printfi_filtered (spaces, "private_field_bits (%d bits at *0x%lx)",
+ TYPE_NFIELDS (type),
+ (unsigned long) TYPE_FIELD_PRIVATE_BITS (type));
+ print_bit_vector (TYPE_FIELD_PRIVATE_BITS (type),
+ TYPE_NFIELDS (type));
+ puts_filtered ("\n");
+ }
+ if (TYPE_FIELD_PROTECTED_BITS (type) != NULL)
+ {
+ printfi_filtered (spaces, "protected_field_bits (%d bits at *0x%lx)",
+ TYPE_NFIELDS (type),
+ (unsigned long) TYPE_FIELD_PROTECTED_BITS (type));
+ print_bit_vector (TYPE_FIELD_PROTECTED_BITS (type),
+ TYPE_NFIELDS (type));
+ puts_filtered ("\n");
+ }
+ }
+ if (TYPE_NFN_FIELDS (type) > 0)
+ {
+ dump_fn_fieldlists (type, spaces);
+ }
+}
+
+void
+recursive_dump_type (type, spaces)
+ struct type *type;
+ int spaces;
+{
+ int idx;
+
+ printfi_filtered (spaces, "type node 0x%lx\n", (unsigned long)type);
+ printfi_filtered (spaces, "name '%s' (0x%lx)\n",
+ TYPE_NAME (type) ? TYPE_NAME (type) : "<NULL>",
+ (unsigned long)TYPE_NAME (type));
+ if (TYPE_TAG_NAME (type) != NULL)
+ printfi_filtered (spaces, "tagname '%s' (0x%lx)\n",
+ TYPE_TAG_NAME (type),
+ (unsigned long)TYPE_TAG_NAME (type));
+ printfi_filtered (spaces, "code 0x%x ", TYPE_CODE (type));
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_UNDEF:
+ printf_filtered ("(TYPE_CODE_UNDEF)");
+ break;
+ case TYPE_CODE_PTR:
+ printf_filtered ("(TYPE_CODE_PTR)");
+ break;
+ case TYPE_CODE_ARRAY:
+ printf_filtered ("(TYPE_CODE_ARRAY)");
+ break;
+ case TYPE_CODE_STRUCT:
+ printf_filtered ("(TYPE_CODE_STRUCT)");
+ break;
+ case TYPE_CODE_UNION:
+ printf_filtered ("(TYPE_CODE_UNION)");
+ break;
+ case TYPE_CODE_ENUM:
+ printf_filtered ("(TYPE_CODE_ENUM)");
+ break;
+ case TYPE_CODE_FUNC:
+ printf_filtered ("(TYPE_CODE_FUNC)");
+ break;
+ case TYPE_CODE_INT:
+ printf_filtered ("(TYPE_CODE_INT)");
+ break;
+ case TYPE_CODE_FLT:
+ printf_filtered ("(TYPE_CODE_FLT)");
+ break;
+ case TYPE_CODE_VOID:
+ printf_filtered ("(TYPE_CODE_VOID)");
+ break;
+ case TYPE_CODE_SET:
+ printf_filtered ("(TYPE_CODE_SET)");
+ break;
+ case TYPE_CODE_RANGE:
+ printf_filtered ("(TYPE_CODE_RANGE)");
+ break;
+ case TYPE_CODE_STRING:
+ printf_filtered ("(TYPE_CODE_STRING)");
+ break;
+ case TYPE_CODE_ERROR:
+ printf_filtered ("(TYPE_CODE_ERROR)");
+ break;
+ case TYPE_CODE_MEMBER:
+ printf_filtered ("(TYPE_CODE_MEMBER)");
+ break;
+ case TYPE_CODE_METHOD:
+ printf_filtered ("(TYPE_CODE_METHOD)");
+ break;
+ case TYPE_CODE_REF:
+ printf_filtered ("(TYPE_CODE_REF)");
+ break;
+ case TYPE_CODE_CHAR:
+ printf_filtered ("(TYPE_CODE_CHAR)");
+ break;
+ case TYPE_CODE_BOOL:
+ printf_filtered ("(TYPE_CODE_BOOL)");
+ break;
+ default:
+ printf_filtered ("(UNKNOWN TYPE CODE)");
+ break;
+ }
+ puts_filtered ("\n");
+ printfi_filtered (spaces, "length %d\n", TYPE_LENGTH (type));
+ printfi_filtered (spaces, "objfile 0x%lx\n",
+ (unsigned long) TYPE_OBJFILE (type));
+ printfi_filtered (spaces, "target_type 0x%lx\n",
+ (unsigned long) TYPE_TARGET_TYPE (type));
+ if (TYPE_TARGET_TYPE (type) != NULL)
+ {
+ recursive_dump_type (TYPE_TARGET_TYPE (type), spaces + 2);
+ }
+ printfi_filtered (spaces, "pointer_type 0x%lx\n",
+ (unsigned long) TYPE_POINTER_TYPE (type));
+ printfi_filtered (spaces, "reference_type 0x%lx\n",
+ (unsigned long) TYPE_REFERENCE_TYPE (type));
+ printfi_filtered (spaces, "function_type 0x%lx\n",
+ (unsigned long) TYPE_FUNCTION_TYPE (type));
+ printfi_filtered (spaces, "flags 0x%x", TYPE_FLAGS (type));
+ if (TYPE_FLAGS (type) & TYPE_FLAG_UNSIGNED)
+ {
+ puts_filtered (" TYPE_FLAG_UNSIGNED");
+ }
+ if (TYPE_FLAGS (type) & TYPE_FLAG_SIGNED)
+ {
+ puts_filtered (" TYPE_FLAG_SIGNED");
+ }
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ {
+ puts_filtered (" TYPE_FLAG_STUB");
+ }
+ puts_filtered ("\n");
+ printfi_filtered (spaces, "nfields %d 0x%lx\n", TYPE_NFIELDS (type),
+ (unsigned long) TYPE_FIELDS (type));
+ for (idx = 0; idx < TYPE_NFIELDS (type); idx++)
+ {
+ printfi_filtered (spaces + 2,
+ "[%d] bitpos %d bitsize %d type 0x%lx name '%s' (0x%lx)\n",
+ idx, TYPE_FIELD_BITPOS (type, idx),
+ TYPE_FIELD_BITSIZE (type, idx),
+ (unsigned long) TYPE_FIELD_TYPE (type, idx),
+ TYPE_FIELD_NAME (type, idx) != NULL
+ ? TYPE_FIELD_NAME (type, idx)
+ : "<NULL>",
+ (unsigned long) TYPE_FIELD_NAME (type, idx));
+ if (TYPE_FIELD_TYPE (type, idx) != NULL)
+ {
+ recursive_dump_type (TYPE_FIELD_TYPE (type, idx), spaces + 4);
+ }
+ }
+ printfi_filtered (spaces, "vptr_basetype 0x%lx\n",
+ (unsigned long) TYPE_VPTR_BASETYPE (type));
+ if (TYPE_VPTR_BASETYPE (type) != NULL)
+ {
+ recursive_dump_type (TYPE_VPTR_BASETYPE (type), spaces + 2);
+ }
+ printfi_filtered (spaces, "vptr_fieldno %d\n", TYPE_VPTR_FIELDNO (type));
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_FUNC:
+ printfi_filtered (spaces, "arg_types 0x%lx\n",
+ (unsigned long) TYPE_ARG_TYPES (type));
+ print_arg_types (TYPE_ARG_TYPES (type), spaces);
+ break;
+
+ case TYPE_CODE_STRUCT:
+ printfi_filtered (spaces, "cplus_stuff 0x%lx\n",
+ (unsigned long) TYPE_CPLUS_SPECIFIC (type));
+ print_cplus_stuff (type, spaces);
+ break;
+
+ default:
+ /* We have to pick one of the union types to be able print and test
+ the value. Pick cplus_struct_type, even though we know it isn't
+ any particular one. */
+ printfi_filtered (spaces, "type_specific 0x%lx",
+ (unsigned long) TYPE_CPLUS_SPECIFIC (type));
+ if (TYPE_CPLUS_SPECIFIC (type) != NULL)
+ {
+ printf_filtered (" (unknown data form)");
+ }
+ printf_filtered ("\n");
+ break;
+
+ }
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+void
+_initialize_gdbtypes ()
+{
+ builtin_type_void =
+ init_type (TYPE_CODE_VOID, 1,
+ 0,
+ "void", (struct objfile *) NULL);
+ builtin_type_char =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "char", (struct objfile *) NULL);
+ builtin_type_signed_char =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED,
+ "signed char", (struct objfile *) NULL);
+ builtin_type_unsigned_char =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned char", (struct objfile *) NULL);
+ builtin_type_short =
+ init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "short", (struct objfile *) NULL);
+ builtin_type_unsigned_short =
+ init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned short", (struct objfile *) NULL);
+ builtin_type_int =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "int", (struct objfile *) NULL);
+ builtin_type_unsigned_int =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ builtin_type_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0,
+ "long", (struct objfile *) NULL);
+ builtin_type_unsigned_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
+ builtin_type_long_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0,
+ "long long", (struct objfile *) NULL);
+ builtin_type_unsigned_long_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long long", (struct objfile *) NULL);
+ builtin_type_float =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "float", (struct objfile *) NULL);
+ builtin_type_double =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double", (struct objfile *) NULL);
+ builtin_type_long_double =
+ init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "long double", (struct objfile *) NULL);
+ builtin_type_complex =
+ init_type (TYPE_CODE_FLT, TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex", (struct objfile *) NULL);
+ builtin_type_double_complex =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double complex", (struct objfile *) NULL);
+ builtin_type_string =
+ init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "string", (struct objfile *) NULL);
+}
diff --git a/gnu/usr.bin/gdb/gdb/gdbtypes.h b/gnu/usr.bin/gdb/gdb/gdbtypes.h
new file mode 100644
index 000000000000..89cad6cbbe5d
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/gdbtypes.h
@@ -0,0 +1,704 @@
+/* Internal type definitions for GDB.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (GDBTYPES_H)
+#define GDBTYPES_H 1
+
+/* When gdb creates fundamental types, it uses one of the following
+ type identifiers. The identifiers are used to index a vector of
+ pointers to any types that are created. */
+
+#define FT_VOID 0
+#define FT_BOOLEAN 1
+#define FT_CHAR 2
+#define FT_SIGNED_CHAR 3
+#define FT_UNSIGNED_CHAR 4
+#define FT_SHORT 5
+#define FT_SIGNED_SHORT 6
+#define FT_UNSIGNED_SHORT 7
+#define FT_INTEGER 8
+#define FT_SIGNED_INTEGER 9
+#define FT_UNSIGNED_INTEGER 10
+#define FT_LONG 11
+#define FT_SIGNED_LONG 12
+#define FT_UNSIGNED_LONG 13
+#define FT_LONG_LONG 14
+#define FT_SIGNED_LONG_LONG 15
+#define FT_UNSIGNED_LONG_LONG 16
+#define FT_FLOAT 17
+#define FT_DBL_PREC_FLOAT 18
+#define FT_EXT_PREC_FLOAT 19
+#define FT_COMPLEX 20
+#define FT_DBL_PREC_COMPLEX 21
+#define FT_EXT_PREC_COMPLEX 22
+#define FT_STRING 23
+#define FT_FIXED_DECIMAL 24
+#define FT_FLOAT_DECIMAL 25
+#define FT_BYTE 26
+#define FT_UNSIGNED_BYTE 27
+
+#define FT_NUM_MEMBERS 28 /* Highest FT_* above, plus one. */
+
+/* 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) memset ((a), 0, B_BYTES(x))
+
+/* 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 with lower & upper bounds. */
+ 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 */
+
+ /* Floating type. This is *NOT* a complex type. Complex types, when
+ we have them, will have their own type code (or TYPE_CODE_ERROR if
+ we can parse a complex type but not manipulate it). There are parts
+ of GDB which bogusly assume that TYPE_CODE_FLT can mean complex. */
+ TYPE_CODE_FLT,
+
+ /* Void type (values zero length; the length field is ignored). */
+ TYPE_CODE_VOID,
+
+ TYPE_CODE_SET, /* Pascal sets */
+ TYPE_CODE_RANGE, /* Range (integers within spec'd bounds) */
+ TYPE_CODE_STRING, /* String types, distinct from array of char */
+ TYPE_CODE_BITSTRING, /* String of bits, distinct from bool array */
+
+ /* Unknown type. The length field is valid if we were able to
+ deduce that much about the type, or 0 if we don't even know that. */
+ TYPE_CODE_ERROR,
+
+ /* C++ */
+ TYPE_CODE_MEMBER, /* Member type */
+ TYPE_CODE_METHOD, /* Method type */
+ TYPE_CODE_REF, /* C++ Reference types */
+
+ /* Modula-2 */
+ TYPE_CODE_CHAR, /* *real* character type */
+ TYPE_CODE_BOOL /* BOOLEAN type */
+};
+
+/* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
+ alias for TYPE_CODE_STRUCT. Eventually these should probably be
+ officially distinct types within gdb. */
+
+#define TYPE_CODE_CLASS TYPE_CODE_STRUCT
+
+/* Some bits for the type's flags word. */
+
+/* Explicitly unsigned integer type */
+
+#define TYPE_FLAG_UNSIGNED (1 << 0)
+
+/* Explicitly signed integer type */
+
+#define TYPE_FLAG_SIGNED (1 << 1)
+
+/* This appears in a type's flags word if it is a stub type (e.g., if
+ someone referenced a type that wasn't defined in a source file
+ via (struct sir_not_appearing_in_this_film *)). */
+
+#define TYPE_FLAG_STUB (1 << 2)
+
+
+struct type
+{
+
+ /* Code for kind of type */
+
+ enum type_code code;
+
+ /* Name of this type, or NULL if none.
+
+ This is used for printing only, except by poorly designed C++ code.
+ For looking up a name, look for a symbol in the VAR_NAMESPACE. */
+
+ char *name;
+
+ /* Tag name for this type, or NULL if none. This means that the
+ name of the type consists of a keyword followed by the tag name.
+ Which keyword is determined by the type code ("struct" for
+ TYPE_CODE_STRUCT, etc.). As far as I know C/C++ are the only languages
+ with this feature.
+
+ This is used for printing only, except by poorly designed C++ code.
+ For looking up a name, look for a symbol in the STRUCT_NAMESPACE.
+ One more legitimate use is that if TYPE_FLAG_STUB is set, this is
+ the name to use to look for definitions in other files. */
+
+ char *tag_name;
+
+ /* Length, in units of TARGET_CHAR_BIT bits,
+ of storage for a value of this type */
+
+ unsigned length;
+
+ /* Every type is now associated with a particular objfile, and the
+ type is allocated on the type_obstack for that objfile. One problem
+ however, is that there are times when gdb allocates new types while
+ it is not in the process of reading symbols from a particular objfile.
+ Fortunately, these happen when the type being created is a derived
+ type of an existing type, such as in lookup_pointer_type(). So
+ we can just allocate the new type using the same objfile as the
+ existing type, but to do this we need a backpointer to the objfile
+ from the existing type. Yes this is somewhat ugly, but without
+ major overhaul of the internal type system, it can't be avoided
+ for now. */
+
+ struct objfile *objfile;
+
+ /* 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 return 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.
+ NULL 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;
+
+ /* Type that is a function returning this type.
+ NULL 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;
+
+ /* 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".
+ For C++ classes, there is one field for each base class (if it is
+ a derived class) plus one field for each class data member. Member
+ functions are recorded elsewhere.
+
+ 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.
+ (FIXME: What about ranges larger than host int size?)
+ For BITS_BIG_ENDIAN=1 targets, it is the bit offset to the MSB.
+ For BITS_BIG_ENDIAN=0 targets, it is the bit offset to the LSB. */
+
+ 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. */
+ /* FIXME: This is abused by TYPE_FIELD_STATIC_PHYSNAME to contain
+ a pointer, so it has to be long. */
+
+ long 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.
+ NULL for range bounds and array domains. */
+
+ char *name;
+
+ } *fields;
+
+ /* For types with virtual functions, VPTR_BASETYPE is the base class which
+ defined the virtual function table pointer.
+
+ For types that are pointer to member types, VPTR_BASETYPE
+ is the type that this pointer is a member of.
+
+ Unused otherwise. */
+
+ struct type *vptr_basetype;
+
+ /* Field number of the virtual function table pointer in
+ VPTR_BASETYPE. If -1, we were unable to find the virtual
+ function table pointer in initial symbol reading, and
+ fill_in_vptr_fieldno should be called to find it if possible.
+
+ Unused if this type does not have virtual functions. */
+
+ int vptr_fieldno;
+
+ /* Slot to point to additional language-specific fields of this type. */
+
+ union type_specific
+ {
+
+ /* ARG_TYPES is for TYPE_CODE_METHOD and TYPE_CODE_FUNC. */
+
+ struct type **arg_types;
+
+ /* CPLUS_STUFF is for TYPE_CODE_STRUCT. It is initialized to point to
+ cplus_struct_default, a default static instance of a struct
+ cplus_struct_type. */
+
+ struct cplus_struct_type *cplus_stuff;
+
+ } type_specific;
+};
+
+#define NULL_TYPE ((struct type *) 0)
+
+/* C++ language-specific information for TYPE_CODE_STRUCT and TYPE_CODE_UNION
+ nodes. */
+
+struct cplus_struct_type
+{
+ /* Number of base classes this type derives from. The baseclasses are
+ stored in the first N_BASECLASSES fields (i.e. the `fields' field of
+ the struct type). I think only the `type' field of such a field has
+ any meaning. */
+
+ short n_baseclasses;
+
+ /* Number of methods with unique names. All overloaded methods with
+ the same name count only once. */
+
+ short nfn_fields;
+
+ /* Number of methods described for this type plus all the
+ methods that it derives from. */
+
+ int nfn_fields_total;
+
+ /* For derived classes, the number of base classes is given by n_baseclasses
+ and virtual_field_bits is a bit vector containing one bit per base class.
+ If the base class is virtual, the corresponding bit will be set.
+ I.E, given:
+
+ class A{};
+ class B{};
+ class 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. */
+
+ B_TYPE *virtual_field_bits;
+
+ /* For classes with private fields, the number of fields is given by
+ nfields and private_field_bits is a bit vector containing one bit
+ per field.
+ If the field is private, the corresponding bit will be set. */
+
+ B_TYPE *private_field_bits;
+
+ /* For classes with protected fields, the number of fields is given by
+ nfields and protected_field_bits is a bit vector containing one bit
+ per field.
+ If the field is private, the corresponding bit will be set. */
+
+ B_TYPE *protected_field_bits;
+
+ /* 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.
+
+ fn_fieldlists points to an array of nfn_fields of these. */
+
+ 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 is_stub is clear, this is the mangled name which we can
+ look up to find the address of the method (FIXME: it would
+ be cleaner to have a pointer to the struct symbol here
+ instead). */
+
+ /* If is_stub is set, this is the portion of the mangled
+ name which specifies the arguments. For example, "ii",
+ if there are two int arguments, or "" if there are no
+ arguments. See gdb_mangle_name for the conversion from this
+ format to the one used if is_stub is clear. */
+
+ char *physname;
+
+ /* The return value of the method */
+
+ struct type *type;
+
+ /* The argument list. Only valid if is_stub is clear. Contains
+ the type of each argument, including `this', and ending with
+ a NULL pointer after the last argument. */
+
+ struct type **args;
+
+ /* For virtual functions.
+ First baseclass that defines this virtual function. */
+
+ struct type *fcontext;
+
+ /* Attributes. */
+
+ unsigned int is_const : 1;
+ unsigned int is_volatile : 1;
+ unsigned int is_private : 1;
+ unsigned int is_protected : 1;
+
+ /* A stub method only has some fields valid (but they are enough
+ to reconstruct the rest of the fields). */
+ unsigned int is_stub : 1;
+
+ /* Unused. */
+ unsigned int dummy : 3;
+
+ /* Index into that baseclass's virtual function table,
+ minus 2; else if static: VOFFSET_STATIC; else: 0. */
+
+ unsigned int voffset : 24;
+
+# define VOFFSET_STATIC 1
+
+ } *fn_fields;
+
+ } *fn_fieldlists;
+
+};
+
+/* The default value of TYPE_CPLUS_SPECIFIC(T) points to the
+ this shared static structure. */
+
+extern const struct cplus_struct_type cplus_struct_default;
+
+extern void
+allocate_cplus_struct_type PARAMS ((struct type *));
+
+#define INIT_CPLUS_SPECIFIC(type) \
+ (TYPE_CPLUS_SPECIFIC(type)=(struct cplus_struct_type*)&cplus_struct_default)
+#define ALLOCATE_CPLUS_STRUCT_TYPE(type) allocate_cplus_struct_type (type)
+#define HAVE_CPLUS_STRUCT(type) \
+ (TYPE_CPLUS_SPECIFIC(type) != &cplus_struct_default)
+
+#define TYPE_NAME(thistype) (thistype)->name
+#define TYPE_TAG_NAME(type) ((type)->tag_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_LENGTH(thistype) (thistype)->length
+#define TYPE_OBJFILE(thistype) (thistype)->objfile
+#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) TYPE_CPLUS_SPECIFIC(thistype)->fn_fields
+#define TYPE_NFN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields
+#define TYPE_NFN_FIELDS_TOTAL(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields_total
+#define TYPE_TYPE_SPECIFIC(thistype) (thistype)->type_specific
+#define TYPE_ARG_TYPES(thistype) (thistype)->type_specific.arg_types
+#define TYPE_CPLUS_SPECIFIC(thistype) (thistype)->type_specific.cplus_stuff
+#define TYPE_BASECLASS(thistype,index) (thistype)->fields[index].type
+#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(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(TYPE_CPLUS_SPECIFIC(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) \
+ TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits
+#define TYPE_FIELD_PROTECTED_BITS(thistype) \
+ TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits
+#define TYPE_FIELD_VIRTUAL_BITS(thistype) \
+ TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits
+#define SET_TYPE_FIELD_PRIVATE(thistype, n) \
+ B_SET (TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits, (n))
+#define SET_TYPE_FIELD_PROTECTED(thistype, n) \
+ B_SET (TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits, (n))
+#define SET_TYPE_FIELD_VIRTUAL(thistype, n) \
+ B_SET (TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n))
+#define TYPE_FIELD_PRIVATE(thistype, n) \
+ (TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits == NULL ? 0 \
+ : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits, (n)))
+#define TYPE_FIELD_PROTECTED(thistype, n) \
+ (TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits == NULL ? 0 \
+ : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->protected_field_bits, (n)))
+#define TYPE_FIELD_VIRTUAL(thistype, n) \
+ B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (n))
+
+#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) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists
+#define TYPE_FN_FIELDLIST(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n]
+#define TYPE_FN_FIELDLIST1(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].fn_fields
+#define TYPE_FN_FIELDLIST_NAME(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].name
+#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].length
+
+#define TYPE_FN_FIELD(thisfn, n) (thisfn)[n]
+#define TYPE_FN_FIELD_PHYSNAME(thisfn, n) (thisfn)[n].physname
+#define TYPE_FN_FIELD_TYPE(thisfn, n) (thisfn)[n].type
+#define TYPE_FN_FIELD_ARGS(thisfn, n) TYPE_ARG_TYPES ((thisfn)[n].type)
+#define TYPE_FN_FIELD_CONST(thisfn, n) ((thisfn)[n].is_const)
+#define TYPE_FN_FIELD_VOLATILE(thisfn, n) ((thisfn)[n].is_volatile)
+#define TYPE_FN_FIELD_PRIVATE(thisfn, n) ((thisfn)[n].is_private)
+#define TYPE_FN_FIELD_PROTECTED(thisfn, n) ((thisfn)[n].is_protected)
+#define TYPE_FN_FIELD_STUB(thisfn, n) ((thisfn)[n].is_stub)
+#define TYPE_FN_FIELD_FCONTEXT(thisfn, n) ((thisfn)[n].fcontext)
+#define TYPE_FN_FIELD_VOFFSET(thisfn, n) ((thisfn)[n].voffset-2)
+#define TYPE_FN_FIELD_VIRTUAL_P(thisfn, n) ((thisfn)[n].voffset > 1)
+#define TYPE_FN_FIELD_STATIC_P(thisfn, n) ((thisfn)[n].voffset == VOFFSET_STATIC)
+
+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_signed_char;
+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;
+extern struct type *builtin_type_long_double;
+extern struct type *builtin_type_complex;
+extern struct type *builtin_type_double_complex;
+extern struct type *builtin_type_string;
+
+/* This type represents a type that was unrecognized in symbol
+ read-in. */
+
+extern struct type *builtin_type_error;
+
+extern struct type *builtin_type_long_long;
+extern struct type *builtin_type_unsigned_long_long;
+
+/* Modula-2 types */
+
+extern struct type *builtin_type_m2_char;
+extern struct type *builtin_type_m2_int;
+extern struct type *builtin_type_m2_card;
+extern struct type *builtin_type_m2_real;
+extern struct type *builtin_type_m2_bool;
+
+/* Chill types */
+
+extern struct type *builtin_type_chill_bool;
+extern struct type *builtin_type_chill_char;
+extern struct type *builtin_type_chill_long;
+extern struct type *builtin_type_chill_ulong;
+extern struct type *builtin_type_chill_real;
+
+/* CC_HAS_LONG_LONG is defined if the host has "long long". */
+
+#ifdef CC_HAS_LONG_LONG
+
+#define BUILTIN_TYPE_LONGEST builtin_type_long_long
+#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long_long
+
+#else /* not CC_HAS_LONG_LONG. */
+
+#define BUILTIN_TYPE_LONGEST builtin_type_long
+#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long
+
+#endif /* not CC_HAS_LONG_LONG. */
+
+/* Maximum and minimum values of built-in types */
+
+#define MAX_OF_TYPE(t) \
+ TYPE_UNSIGNED(t) ? UMAX_OF_SIZE(TYPE_LENGTH(t)) \
+ : MAX_OF_SIZE(TYPE_LENGTH(t))
+
+#define MIN_OF_TYPE(t) \
+ TYPE_UNSIGNED(t) ? UMIN_OF_SIZE(TYPE_LENGTH(t)) \
+ : MIN_OF_SIZE(TYPE_LENGTH(t))
+
+/* Allocate space for storing data associated with a particular type.
+ We ensure that the space is allocated using the same mechanism that
+ was used to allocate the space for the type structure itself. I.E.
+ if the type is on an objfile's type_obstack, then the space for data
+ associated with that type will also be allocated on the type_obstack.
+ If the type is not associated with any particular objfile (such as
+ builtin types), then the data space will be allocated with xmalloc,
+ the same as for the type structure. */
+
+#define TYPE_ALLOC(t,size) \
+ (TYPE_OBJFILE (t) != NULL \
+ ? obstack_alloc (&TYPE_OBJFILE (t) -> type_obstack, size) \
+ : xmalloc (size))
+
+extern struct type *
+alloc_type PARAMS ((struct objfile *));
+
+extern struct type *
+init_type PARAMS ((enum type_code, int, int, char *, struct objfile *));
+
+extern struct type *
+lookup_reference_type PARAMS ((struct type *));
+
+extern struct type *
+make_reference_type PARAMS ((struct type *, struct type **));
+
+extern struct type *
+lookup_member_type PARAMS ((struct type *, struct type *));
+
+extern void
+smash_to_method_type PARAMS ((struct type *, struct type *, struct type *,
+ struct type **));
+
+extern void
+smash_to_member_type PARAMS ((struct type *, struct type *, struct type *));
+
+extern struct type *
+allocate_stub_method PARAMS ((struct type *));
+
+extern char *
+type_name_no_tag PARAMS ((const struct type *));
+
+extern struct type *
+lookup_struct_elt_type PARAMS ((struct type *, char *, int));
+
+extern struct type *
+make_pointer_type PARAMS ((struct type *, struct type **));
+
+extern struct type *
+lookup_pointer_type PARAMS ((struct type *));
+
+extern struct type *
+make_function_type PARAMS ((struct type *, struct type **));
+
+extern struct type *
+lookup_function_type PARAMS ((struct type *));
+
+extern struct type *
+create_range_type PARAMS ((struct type *, struct type *, int, int));
+
+extern struct type *
+create_array_type PARAMS ((struct type *, struct type *, struct type *));
+
+extern struct type *
+create_string_type PARAMS ((struct type *, struct type *));
+
+extern struct type *
+lookup_unsigned_typename PARAMS ((char *));
+
+extern struct type *
+lookup_signed_typename PARAMS ((char *));
+
+extern void
+check_stub_type PARAMS ((struct type *));
+
+extern void
+check_stub_method PARAMS ((struct type *, int, int));
+
+extern struct type *
+lookup_primitive_typename PARAMS ((char *));
+
+extern char *
+gdb_mangle_name PARAMS ((struct type *, int, int));
+
+extern struct type *
+builtin_type PARAMS ((char **));
+
+extern struct type *
+lookup_typename PARAMS ((char *, struct block *, int));
+
+extern struct type *
+lookup_template_type PARAMS ((char *, struct type *, struct block *));
+
+extern struct type *
+lookup_fundamental_type PARAMS ((struct objfile *, int));
+
+extern void
+fill_in_vptr_fieldno PARAMS ((struct type *));
+
+#if MAINTENANCE_CMDS
+extern void recursive_dump_type PARAMS ((struct type *, int));
+#endif
+
+/* printcmd.c */
+
+extern void
+print_scalar_formatted PARAMS ((char *, struct type *, int, int, FILE *));
+
+#if MAINTENANCE_CMDS
+extern void maintenance_print_type PARAMS ((char *, int));
+#endif
+
+#endif /* GDBTYPES_H */
diff --git a/gnu/usr.bin/gdb/gdb/getopt.h b/gnu/usr.bin/gdb/gdb/getopt.h
new file mode 100644
index 000000000000..1b546b2e330c
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/getopt.h
@@ -0,0 +1,129 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License
+ as published by the Free Software Foundation; either version 2, or
+ (at your option) any later version.
+
+ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, 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.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if __STDC__
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* not __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/gnu/usr.bin/gdb/config/i386-pinsn.c b/gnu/usr.bin/gdb/gdb/i386-dis.c
index 649baaf56bf6..3e4bbb225e63 100644
--- a/gnu/usr.bin/gdb/config/i386-pinsn.c
+++ b/gnu/usr.bin/gdb/gdb/i386-dis.c
@@ -1,25 +1,26 @@
/* Print i386 instructions for GDB, the GNU debugger.
- Copyright (C) 1988, 1989 Free Software Foundation, Inc.
+ 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
+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.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
+ * modified by John Hassey (hassey@dg-rtp.dg.com)
*/
/*
@@ -31,8 +32,50 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
* the Intel manual for details.
*/
-#include <stdio.h>
-#include <ctype.h>
+#include "dis-asm.h"
+
+#define MAXLEN 20
+
+#include <setjmp.h>
+
+struct private
+{
+ /* Points to first byte not fetched. */
+ bfd_byte *max_fetched;
+ bfd_byte the_buffer[MAXLEN];
+ bfd_vma insn_start;
+ jmp_buf bailout;
+};
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+ to ADDR (exclusive) are valid. Returns 1 for success, longjmps
+ on error. */
+#define FETCH_DATA(info, addr) \
+ ((addr) <= ((struct private *)(info->private_data))->max_fetched \
+ ? 1 : fetch_data ((info), (addr)))
+
+static int
+fetch_data (info, addr)
+ struct disassemble_info *info;
+ bfd_byte *addr;
+{
+ int status;
+ struct private *priv = (struct private *)info->private_data;
+ bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
+
+ status = (*info->read_memory_func) (start,
+ priv->max_fetched,
+ addr - priv->max_fetched,
+ info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, start, info);
+ longjmp (priv->bailout, 1);
+ }
+ else
+ priv->max_fetched = addr;
+ return 1;
+}
#define Eb OP_E, b_mode
#define indirEb OP_indirE, b_mode
@@ -100,6 +143,8 @@ 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();
+static void dofloat (), putop (), append_prefix (), set_op ();
+static int get16 (), get32 ();
#define b_mode 1
#define v_mode 2
@@ -475,7 +520,9 @@ struct dis386 dis386_twobyte[] = {
{ "clts" },
{ "(bad)" },
/* 08 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "invd" },
+ { "wbinvd" },
+ { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* 10 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
@@ -581,8 +628,8 @@ struct dis386 dis386_twobyte[] = {
{ "(bad)" },
{ "imulS", Gv, Ev },
/* b0 */
- { "(bad)" },
- { "(bad)" },
+ { "cmpxchgb", Eb, Gb },
+ { "cmpxchgS", Ev, Gv },
{ "lssS", Gv, Mp }, /* 386 lists only Mp */
{ "btrS", Ev, Gv },
{ "lfsS", Gv, Mp }, /* 386 lists only Mp */
@@ -599,11 +646,19 @@ struct dis386 dis386_twobyte[] = {
{ "movsbS", Gv, Eb },
{ "movswS", Gv, Ew },
/* c0 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "xaddb", Eb, Gb },
+ { "xaddS", Ev, Gv },
+ { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
/* c8 */
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
- { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "bswap", eAX },
+ { "bswap", eCX },
+ { "bswap", eDX },
+ { "bswap", eBX },
+ { "bswap", eSP },
+ { "bswap", eBP },
+ { "bswap", eSI },
+ { "bswap", eDI },
/* d0 */
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
{ "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
@@ -629,9 +684,11 @@ static char *obufp;
static char scratchbuf[100];
static unsigned char *start_codep;
static unsigned char *codep;
+static disassemble_info *the_info;
static int mod;
static int rm;
static int reg;
+static void oappend ();
static char *names32[]={
"%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
@@ -810,7 +867,7 @@ struct dis386 grps[][8] = {
{ "smsw", Ew },
{ "(bad)" },
{ "lmsw", Ew },
- { "(bad)" },
+ { "invlpg", Ew },
},
/* GRP8 */
{
@@ -840,11 +897,13 @@ struct dis386 grps[][8] = {
static int prefixes;
+static void
ckprefix ()
{
prefixes = 0;
while (1)
{
+ FETCH_DATA (the_info, codep + 1);
switch (*codep)
{
case 0xf3:
@@ -894,44 +953,55 @@ 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;
+
/*
- * 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, outbuf)
- int pc;
- unsigned char *inbuf;
- char *outbuf;
+
+int
+print_insn_i386 (pc, info)
+ bfd_vma pc;
+ disassemble_info *info;
{
struct dis386 *dp;
- char *p;
int i;
int enter_instruction;
char *first, *second, *third;
int needcomma;
+ struct private priv;
+ bfd_byte *inbuf = priv.the_buffer;
+
+ info->private_data = (PTR) &priv;
+ priv.max_fetched = priv.the_buffer;
+ priv.insn_start = pc;
+ if (setjmp (priv.bailout) != 0)
+ /* Error return. */
+ return -1;
+
obuf[0] = 0;
op1out[0] = 0;
op2out[0] = 0;
op3out[0] = 0;
-
+
+ op_index[0] = op_index[1] = op_index[2] = -1;
+
+ the_info = info;
start_pc = pc;
start_codep = inbuf;
codep = inbuf;
ckprefix ();
-
+
+ FETCH_DATA (info, codep + 1);
if (*codep == 0xc8)
enter_instruction = 1;
else
@@ -950,8 +1020,7 @@ i386dis (pc, inbuf, outbuf)
&& ((*codep < 0xd8) || (*codep > 0xdf)))
{
/* fwait not followed by floating point instruction */
- oappend ("fwait");
- strcpy (outbuf, obuf);
+ (*info->fprintf_func) (info->stream, "fwait");
return (1);
}
@@ -969,10 +1038,14 @@ i386dis (pc, inbuf, outbuf)
}
if (*codep == 0x0f)
- dp = &dis386_twobyte[*++codep];
+ {
+ FETCH_DATA (info, codep + 2);
+ dp = &dis386_twobyte[*++codep];
+ }
else
dp = &dis386[*codep];
codep++;
+ FETCH_DATA (info, codep + 1);
mod = (*codep >> 6) & 3;
reg = (*codep >> 3) & 7;
rm = *codep & 7;
@@ -989,14 +1062,17 @@ i386dis (pc, inbuf, outbuf)
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);
}
@@ -1005,6 +1081,7 @@ i386dis (pc, inbuf, outbuf)
for (i = strlen (obuf); i < 6; i++)
oappend (" ");
oappend (" ");
+ (*info->fprintf_func) (info->stream, "%s", obuf);
/* enter instruction is printed with operands in the
* same order as the intel book; everything else
@@ -1015,6 +1092,9 @@ i386dis (pc, inbuf, outbuf)
first = op1out;
second = op2out;
third = op3out;
+ op_ad = op_index[0];
+ op_index[0] = op_index[2];
+ op_index[2] = op_ad;
}
else
{
@@ -1025,23 +1105,31 @@ i386dis (pc, inbuf, outbuf)
needcomma = 0;
if (*first)
{
- oappend (first);
+ if (op_index[0] != -1)
+ (*info->print_address_func) (op_address[op_index[0]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", first);
needcomma = 1;
}
if (*second)
{
if (needcomma)
- oappend (",");
- oappend (second);
+ (*info->fprintf_func) (info->stream, ",");
+ if (op_index[1] != -1)
+ (*info->print_address_func) (op_address[op_index[1]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", second);
needcomma = 1;
}
if (*third)
{
if (needcomma)
- oappend (",");
- oappend (third);
+ (*info->fprintf_func) (info->stream, ",");
+ if (op_index[2] != -1)
+ (*info->print_address_func) (op_address[op_index[2]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", third);
}
- strcpy (outbuf, obuf);
return (codep - inbuf);
}
@@ -1274,7 +1362,7 @@ char *fgrps[][8] = {
},
};
-
+static void
dofloat ()
{
struct dis386 *dp;
@@ -1296,7 +1384,9 @@ dofloat ()
{
putop (fgrps[dp->bytemode1][rm]);
/* instruction fnstsw is only one with strange arg */
- if (floatop == 0xdf && *codep == 0xe0)
+ if (floatop == 0xdf
+ && FETCH_DATA (the_info, codep + 1)
+ && *codep == 0xe0)
strcpy (op1out, "%eax");
}
else
@@ -1312,20 +1402,27 @@ dofloat ()
}
/* ARGSUSED */
+int
OP_ST (ignore)
+ int ignore;
{
oappend ("%st");
+ return (0);
}
/* ARGSUSED */
+int
OP_STi (ignore)
+ int ignore;
{
sprintf (scratchbuf, "%%st(%d)", rm);
oappend (scratchbuf);
+ return (0);
}
/* capital letters in template are macros */
+static void
putop (template)
char *template;
{
@@ -1358,14 +1455,16 @@ putop (template)
*obufp = 0;
}
+static void
oappend (s)
-char *s;
+ char *s;
{
strcpy (obufp, s);
obufp += strlen (s);
*obufp = 0;
}
+static void
append_prefix ()
{
if (prefixes & PREFIX_CS)
@@ -1382,17 +1481,21 @@ append_prefix ()
oappend ("%gs:");
}
+int
OP_indirE (bytemode)
+ int bytemode;
{
oappend ("*");
OP_E (bytemode);
+ return (0);
}
+int
OP_E (bytemode)
+ int bytemode;
{
int disp;
int havesib;
- int didoutput = 0;
int base;
int index;
int scale;
@@ -1425,7 +1528,7 @@ OP_E (bytemode)
oappend ("<bad dis table>");
break;
}
- return;
+ return (0);
}
append_prefix ();
@@ -1433,6 +1536,7 @@ OP_E (bytemode)
{
havesib = 1;
havebase = 1;
+ FETCH_DATA (the_info, codep + 1);
scale = (*codep >> 6) & 3;
index = (*codep >> 3) & 7;
base = *codep & 7;
@@ -1461,6 +1565,7 @@ OP_E (bytemode)
}
break;
case 1:
+ FETCH_DATA (the_info, codep + 1);
disp = *(char *)codep++;
if (rm != 4)
{
@@ -1480,7 +1585,7 @@ OP_E (bytemode)
if (mod != 0 || rm == 5 || (havesib && base == 5))
{
- sprintf (scratchbuf, "%d", disp);
+ sprintf (scratchbuf, "0x%x", disp);
oappend (scratchbuf);
}
@@ -1501,9 +1606,12 @@ OP_E (bytemode)
}
oappend (")");
}
+ return (0);
}
+int
OP_G (bytemode)
+ int bytemode;
{
switch (bytemode)
{
@@ -1526,12 +1634,15 @@ OP_G (bytemode)
oappend ("<internal disassembler error>");
break;
}
+ return (0);
}
+static int
get32 ()
{
int x = 0;
-
+
+ FETCH_DATA (the_info, codep + 4);
x = *codep++ & 0xff;
x |= (*codep++ & 0xff) << 8;
x |= (*codep++ & 0xff) << 16;
@@ -1539,16 +1650,28 @@ get32 ()
return (x);
}
+static int
get16 ()
{
int x = 0;
-
+
+ FETCH_DATA (the_info, codep + 2);
x = *codep++ & 0xff;
x |= (*codep++ & 0xff) << 8;
return (x);
}
+static void
+set_op (op)
+ int op;
+{
+ op_index[op_ad] = op_ad;
+ op_address[op_ad] = op;
+}
+
+int
OP_REG (code)
+ int code;
{
char *s;
@@ -1579,15 +1702,19 @@ OP_REG (code)
break;
}
oappend (s);
+ return (0);
}
+int
OP_I (bytemode)
+ int bytemode;
{
int op;
switch (bytemode)
{
case b_mode:
+ FETCH_DATA (the_info, codep + 1);
op = *codep++ & 0xff;
break;
case v_mode:
@@ -1601,19 +1728,23 @@ OP_I (bytemode)
break;
default:
oappend ("<internal disassembler error>");
- return;
+ return (0);
}
sprintf (scratchbuf, "$0x%x", op);
oappend (scratchbuf);
+ return (0);
}
+int
OP_sI (bytemode)
+ int bytemode;
{
int op;
switch (bytemode)
{
case b_mode:
+ FETCH_DATA (the_info, codep + 1);
op = *(char *)codep++;
break;
case v_mode:
@@ -1627,13 +1758,16 @@ OP_sI (bytemode)
break;
default:
oappend ("<internal disassembler error>");
- return;
+ return (0);
}
sprintf (scratchbuf, "$0x%x", op);
oappend (scratchbuf);
+ return (0);
}
+int
OP_J (bytemode)
+ int bytemode;
{
int disp;
int mask = -1;
@@ -1641,6 +1775,7 @@ OP_J (bytemode)
switch (bytemode)
{
case b_mode:
+ FETCH_DATA (the_info, codep + 1);
disp = *(char *)codep++;
break;
case v_mode:
@@ -1656,26 +1791,32 @@ OP_J (bytemode)
}
break;
default:
- oappend ("<internal disassembelr error>");
- return;
+ oappend ("<internal disassembler error>");
+ return (0);
}
-
- sprintf (scratchbuf, "0x%x",
- (start_pc + codep - start_codep + disp) & mask);
+ disp = (start_pc + codep - start_codep + disp) & mask;
+ set_op (disp);
+ sprintf (scratchbuf, "0x%x", disp);
oappend (scratchbuf);
+ return (0);
}
/* ARGSUSED */
+int
OP_SEG (dummy)
+ int dummy;
{
static char *sreg[] = {
"%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
};
oappend (sreg[reg]);
+ return (0);
}
+int
OP_DIR (size)
+ int size;
{
int seg, offset;
@@ -1701,18 +1842,22 @@ OP_DIR (size)
else
offset = (short)get16 ();
- sprintf (scratchbuf, "0x%x",
- start_pc + codep - start_codep + offset);
+ offset = start_pc + codep - start_codep + offset;
+ set_op (offset);
+ sprintf (scratchbuf, "0x%x", offset);
oappend (scratchbuf);
break;
default:
oappend ("<internal disassembler error>");
break;
}
+ return (0);
}
/* ARGSUSED */
+int
OP_OFF (bytemode)
+ int bytemode;
{
int off;
@@ -1723,55 +1868,76 @@ OP_OFF (bytemode)
sprintf (scratchbuf, "0x%x", off);
oappend (scratchbuf);
+ return (0);
}
/* ARGSUSED */
+int
OP_ESDI (dummy)
+ int dummy;
{
oappend ("%es:(");
oappend (aflag ? "%edi" : "%di");
oappend (")");
+ return (0);
}
/* ARGSUSED */
+int
OP_DSSI (dummy)
+ int dummy;
{
oappend ("%ds:(");
oappend (aflag ? "%esi" : "%si");
oappend (")");
+ return (0);
}
/* ARGSUSED */
+int
OP_ONE (dummy)
+ int dummy;
{
oappend ("1");
+ return (0);
}
/* ARGSUSED */
+int
OP_C (dummy)
+ int dummy;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%cr%d", reg);
oappend (scratchbuf);
+ return (0);
}
/* ARGSUSED */
+int
OP_D (dummy)
+ int dummy;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%db%d", reg);
oappend (scratchbuf);
+ return (0);
}
/* ARGSUSED */
+int
OP_T (dummy)
+ int dummy;
{
codep++; /* skip mod/rm */
sprintf (scratchbuf, "%%tr%d", reg);
oappend (scratchbuf);
+ return (0);
}
+int
OP_rm (bytemode)
+ int bytemode;
{
switch (bytemode)
{
@@ -1782,31 +1948,5 @@ OP_rm (bytemode)
oappend (names16[rm]);
break;
}
+ return (0);
}
-
-/* GDB interface */
-#include "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-#include "inferior.h"
-
-#define MAXLEN 20
-print_insn (memaddr, stream)
- CORE_ADDR memaddr;
- FILE *stream;
-{
- unsigned char buffer[MAXLEN];
- /* should be expanded if disassembler prints symbol names */
- char outbuf[100];
- int n;
-
- read_memory (memaddr, buffer, MAXLEN);
-
- n = i386dis ((int)memaddr, buffer, outbuf);
-
- fputs (outbuf, stream);
-
- return (n);
-}
-
diff --git a/gnu/usr.bin/gdb/gdb/i386-pinsn.c b/gnu/usr.bin/gdb/gdb/i386-pinsn.c
new file mode 100644
index 000000000000..b6d7fe91e39f
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/i386-pinsn.c
@@ -0,0 +1,37 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "dis-asm.h"
+
+
+/* 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;
+{
+ disassemble_info info;
+
+ GDB_INIT_DISASSEMBLE_INFO(info, stream);
+
+ return print_insn_i386 (memaddr, &info);
+}
diff --git a/gnu/usr.bin/gdb/gdb/i386-tdep.c b/gnu/usr.bin/gdb/gdb/i386-tdep.c
new file mode 100644
index 000000000000..3c64d7224cf0
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/i386-tdep.c
@@ -0,0 +1,595 @@
+/* Intel 386 target-dependent stuff.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+
+static long
+i386_get_frame_setup PARAMS ((int));
+
+static void
+i386_follow_jump PARAMS ((void));
+
+static void
+codestream_read PARAMS ((unsigned char *, int));
+
+static void
+codestream_seek PARAMS ((int));
+
+static unsigned char
+codestream_fill PARAMS ((int));
+
+/* helper functions for tm-i386.h */
+
+/* Stdio style buffering was used to minimize calls to ptrace, but this
+ buffering did not take into account that the code section being accessed
+ may not be an even number of buffers long (even if the buffer is only
+ sizeof(int) long). In cases where the code section size happened to
+ be a non-integral number of buffers long, attempting to read the last
+ buffer would fail. Simply using target_read_memory and ignoring errors,
+ rather than read_memory, is not the correct solution, since legitimate
+ access errors would then be totally ignored. To properly handle this
+ situation and continue to use buffering would require that this code
+ be able to determine the minimum code section size granularity (not the
+ alignment of the section itself, since the actual failing case that
+ pointed out this problem had a section alignment of 4 but was not a
+ multiple of 4 bytes long), on a target by target basis, and then
+ adjust it's buffer size accordingly. This is messy, but potentially
+ feasible. It probably needs the bfd library's help and support. For
+ now, the buffer size is set to 1. (FIXME -fnf) */
+
+#define CODESTREAM_BUFSIZ 1 /* Was sizeof(int), see note above. */
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned char codestream_buf[CODESTREAM_BUFSIZ];
+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)
+ int peek_flag;
+{
+ codestream_addr = codestream_next_addr;
+ codestream_next_addr += CODESTREAM_BUFSIZ;
+ codestream_off = 0;
+ codestream_cnt = CODESTREAM_BUFSIZ;
+ read_memory (codestream_addr, (char *) codestream_buf, CODESTREAM_BUFSIZ);
+
+ if (peek_flag)
+ return (codestream_peek());
+ else
+ return (codestream_get());
+}
+
+static void
+codestream_seek (place)
+ int place;
+{
+ codestream_next_addr = place / CODESTREAM_BUFSIZ;
+ codestream_next_addr *= CODESTREAM_BUFSIZ;
+ codestream_cnt = 0;
+ codestream_fill (1);
+ while (codestream_tell() != place)
+ codestream_get ();
+}
+
+static void
+codestream_read (buf, count)
+ unsigned char *buf;
+ int count;
+{
+ 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 void
+i386_follow_jump ()
+{
+ unsigned char buf[4];
+ long delta;
+
+ int data16;
+ CORE_ADDR 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 (buf, 2);
+ delta = extract_signed_integer (buf, 2);
+
+ /* include size of jmp inst (including the 0x66 prefix). */
+ pos += delta + 4;
+ }
+ else
+ {
+ codestream_read (buf, 4);
+ delta = extract_signed_integer (buf, 4);
+
+ pos += delta + 5;
+ }
+ break;
+ case 0xeb:
+ /* relative jump, disp8 (ignore data16) */
+ codestream_read (buf, 1);
+ /* Sign-extend it. */
+ delta = extract_signed_integer (buf, 1);
+
+ pos += delta + 2;
+ break;
+ }
+ codestream_seek (pos);
+}
+
+/*
+ * 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)
+ int 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 (memcmp (buf, proto1, 3) == 0)
+ pos += 3;
+ else if (memcmp (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)
+ {
+ char buf[4];
+ /* Maybe it is subl with 32 bit immedediate. */
+ codestream_get();
+ if (codestream_get () != 0xec)
+ /* Some instruction starting with 0x81 other than subl. */
+ {
+ codestream_seek (codestream_tell () - 2);
+ return 0;
+ }
+ /* It is subl with 32 bit immediate. */
+ codestream_read ((unsigned char *)buf, 4);
+ return extract_signed_integer (buf, 4);
+ }
+ else
+ {
+ return (0);
+ }
+ }
+ else if (op == 0xc8)
+ {
+ char buf[2];
+ /* enter instruction: arg is 16 bit unsigned immed */
+ codestream_read ((unsigned char *)buf, 2);
+ codestream_get (); /* flush final byte of enter instruction */
+ return extract_unsigned_integer (buf, 2);
+ }
+ return (-1);
+}
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+int
+i386_frame_num_args (fi)
+ struct frame_info *fi;
+{
+#if 1
+ return -1;
+#else
+ /* This loses because not only might the compiler not be popping the
+ args right after the function call, it might be popping args from both
+ this call and a previous one, and we would say there are more args
+ than there really are. */
+
+ int retpc;
+ unsigned char op;
+ struct frame_info *pfi;
+
+ /* 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 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;
+ }
+ }
+#endif
+}
+
+/*
+ * 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.
+ */
+
+void
+i386_frame_find_saved_regs (fip, fsrp)
+ struct frame_info *fip;
+ struct frame_saved_regs *fsrp;
+{
+ long locals;
+ unsigned char op;
+ CORE_ADDR dummy_bottom;
+ CORE_ADDR adr;
+ int i;
+
+ memset (fsrp, 0, 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 */
+
+int
+i386_skip_prologue (pc)
+ int 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 ());
+}
+
+void
+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);
+}
+
+void
+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 ()));
+}
+
+#ifdef GET_LONGJMP_TARGET
+
+/* Figure out where the longjmp will land. Slurp the args out of the stack.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
+ This routine returns true on success. */
+
+int
+get_longjmp_target(pc)
+ CORE_ADDR *pc;
+{
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ CORE_ADDR sp, jb_addr;
+
+ sp = read_register (SP_REGNUM);
+
+ if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
+ buf,
+ TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ return 0;
+
+ jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+
+ if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
+ TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ return 0;
+
+ *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+
+ return 1;
+}
+
+#endif /* GET_LONGJMP_TARGET */
+
+#ifdef I386_AIX_TARGET
+/* On AIX, floating point values are returned in floating point registers. */
+
+void
+i386_extract_return_value(type, regbuf, valbuf)
+ struct type *type;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+ if (TYPE_CODE_FLT == TYPE_CODE(type))
+ {
+ extern struct ext_format ext_format_i387;
+ double d;
+ /* 387 %st(0), gcc uses this */
+ ieee_extended_to_double (&ext_format_i387,
+ &regbuf[REGISTER_BYTE(FP0_REGNUM)],
+ &d);
+ switch (TYPE_LENGTH(type))
+ {
+ case 4: /* float */
+ {
+ float f = (float) d;
+ memcpy (valbuf, &f, 4);
+ break;
+ }
+ case 8: /* double */
+ memcpy (valbuf, &d, 8);
+ break;
+ default:
+ error("Unknown floating point size");
+ break;
+ }
+ }
+ else
+ {
+ memcpy (valbuf, regbuf, TYPE_LENGTH (type));
+ }
+}
+#endif /* I386_AIX_TARGET */
diff --git a/gnu/usr.bin/gdb/gdb/infcmd.c b/gnu/usr.bin/gdb/gdb/infcmd.c
new file mode 100644
index 000000000000..5859ed269f85
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/infcmd.c
@@ -0,0 +1,1423 @@
+/* Memory-access and commands for "inferior" (child) process, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <signal.h>
+#include <sys/param.h>
+#include <string.h>
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "target.h"
+
+static void
+continue_command PARAMS ((char *, int));
+
+static void
+until_next_command PARAMS ((int));
+
+static void
+until_command PARAMS ((char *, int));
+
+static void
+path_info PARAMS ((char *, int));
+
+static void
+path_command PARAMS ((char *, int));
+
+static void
+unset_command PARAMS ((char *, int));
+
+static void
+float_info PARAMS ((char *, int));
+
+static void
+detach_command PARAMS ((char *, int));
+
+static void
+nofp_registers_info PARAMS ((char *, int));
+
+static void
+all_registers_info PARAMS ((char *, int));
+
+static void
+registers_info PARAMS ((char *, int));
+
+static void
+do_registers_info PARAMS ((int, int));
+
+static void
+unset_environment_command PARAMS ((char *, int));
+
+static void
+set_environment_command PARAMS ((char *, int));
+
+static void
+environment_info PARAMS ((char *, int));
+
+static void
+program_info PARAMS ((char *, int));
+
+static void
+finish_command PARAMS ((char *, int));
+
+static void
+signal_command PARAMS ((char *, int));
+
+static void
+jump_command PARAMS ((char *, int));
+
+static void
+step_1 PARAMS ((int, int, char *));
+
+static void
+nexti_command PARAMS ((char *, int));
+
+static void
+stepi_command PARAMS ((char *, int));
+
+static void
+next_command PARAMS ((char *, int));
+
+static void
+step_command PARAMS ((char *, int));
+
+static void
+run_command PARAMS ((char *, int));
+
+#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.
+ 0 means don't step over calls (used by stepi).
+ -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;
+
+
+/* ARGSUSED */
+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 ();
+
+ /* Shouldn't this be target_has_execution? FIXME. */
+ 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 ();
+ }
+
+ exec_file = (char *) get_exec_file (0);
+
+ /* The exec file is re-read every time we do a generic_mourn_inferior, so
+ we just have to worry about the symbol file. */
+ reread_symbols ();
+
+ if (args)
+ {
+ char *cmd;
+ cmd = concat ("set args ", args, NULL);
+ make_cleanup (free, cmd);
+ execute_command (cmd, from_tty);
+ }
+
+ if (from_tty)
+ {
+ puts_filtered("Starting program: ");
+ if (exec_file)
+ puts_filtered(exec_file);
+ puts_filtered(" ");
+ puts_filtered(inferior_args);
+ puts_filtered("\n");
+ fflush (stdout);
+ }
+
+ target_create_inferior (exec_file, inferior_args,
+ environ_vector (inferior_environ));
+}
+
+static 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_filtered (" ");
+ num = bpstat_num (&bs);
+ }
+ }
+
+ if (from_tty)
+ printf_filtered ("Continuing.\n");
+
+ clear_proceed_status ();
+
+ proceed ((CORE_ADDR) -1, -1, 0);
+}
+
+/* Step until outside of current statement. */
+
+/* ARGSUSED */
+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. */
+
+/* ARGSUSED */
+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. */
+
+/* ARGSUSED */
+static void
+stepi_command (count_string, from_tty)
+ char *count_string;
+ int from_tty;
+{
+ step_1 (0, 1, count_string);
+}
+
+/* ARGSUSED */
+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;
+ struct cleanup *cleanups = 0;
+
+ ERROR_NO_INFERIOR;
+ count = count_string ? parse_and_eval_address (count_string) : 1;
+
+ if (!single_inst || skip_subroutines) /* leave si command alone */
+ {
+ enable_longjmp_breakpoint();
+ cleanups = make_cleanup(disable_longjmp_breakpoint, 0);
+ }
+
+ 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)
+ {
+ char *name;
+ if (find_pc_partial_function (stop_pc, &name, &step_range_start,
+ &step_range_end) == 0)
+ error ("Cannot find bounds of current function");
+
+ target_terminal_ours ();
+ printf_filtered ("\
+Single stepping until exit from function %s, \n\
+which has no line number information.\n", name);
+ fflush (stdout);
+ }
+ }
+ else
+ {
+ /* Say we are stepping, but stop after one insn whatever it does. */
+ step_range_start = step_range_end = 1;
+ if (!skip_subroutines)
+ /* It is stepi.
+ Don't step over function calls, not even to functions lacking
+ line numbers. */
+ 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;
+
+ /* FIXME: On nexti, this may have already been done (when we hit the
+ step resume break, I think). Probably this should be moved to
+ wait_for_inferior (near the top). */
+#if defined (SHIFT_INST_REGS)
+ SHIFT_INST_REGS();
+#endif
+ }
+
+ if (!single_inst || skip_subroutines)
+ do_cleanups(cleanups);
+}
+
+/* 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;
+ struct symbol *fn;
+ struct symbol *sfn;
+
+ 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 ((PTR)sals.sals);
+
+ if (sal.symtab == 0 && sal.pc == 0)
+ error ("No source file has been specified.");
+
+ resolve_sal_pc (&sal); /* May error out */
+
+ /* See if we are trying to jump to another function. */
+ fn = get_frame_function (get_current_frame ());
+ sfn = find_pc_function (sal.pc);
+ if (fn != NULL && sfn != fn)
+ {
+ if (!query ("Line %d is not in `%s'. Jump anyway? ", sal.line,
+ SYMBOL_SOURCE_NAME (fn)))
+ {
+ error ("Not confirmed.");
+ /* NOTREACHED */
+ }
+ }
+
+ addr = sal.pc;
+
+ if (from_tty)
+ printf_filtered ("Continuing at %s.\n",
+ local_hex_string((unsigned long) 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");
+
+ /* It would be even slicker to make signal names be valid expressions,
+ (the type could be "enum $signal" or some such), then the user could
+ assign them to convenience variables. */
+ signum = strtosigno (signum_exp);
+
+ if (signum == 0)
+ /* Not found as a name, try it as an expression. */
+ signum = parse_and_eval_address (signum_exp);
+
+ if (from_tty)
+ {
+ char *signame = strsigno (signum);
+ printf_filtered ("Continuing with signal ");
+ if (signame == NULL || signum == 0)
+ printf_filtered ("%d.\n", signum);
+ else
+ /* Do we need to print the number as well as the name? */
+ printf_filtered ("%s (%d).\n", signame, signum);
+ }
+
+ clear_proceed_status ();
+ proceed (stop_pc, signum, 0);
+}
+
+/* Call breakpoint_auto_delete on the current contents of the bpstat
+ pointed to by arg (which is really a bpstat *). */
+void
+breakpoint_auto_delete_contents (arg)
+ PTR arg;
+{
+ breakpoint_auto_delete (*(bpstat *)arg);
+}
+
+/* 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 and returns 0.
+ Otherwise, run_stack-dummy returns 1 (the frame will eventually be popped
+ when we do hit that breakpoint). */
+
+/* DEBUG HOOK: 4 => return instead of letting the stack dummy run. */
+
+static int stack_dummy_testing = 0;
+
+int
+run_stack_dummy (addr, buffer)
+ CORE_ADDR addr;
+ char buffer[REGISTER_BYTES];
+{
+ struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+
+ /* Now proceed, having reached the desired place. */
+ clear_proceed_status ();
+ if (stack_dummy_testing & 4)
+ {
+ POP_FRAME;
+ return(0);
+ }
+#ifdef CALL_DUMMY_BREAKPOINT_OFFSET
+ {
+ struct breakpoint *bpt;
+ struct symtab_and_line sal;
+
+#if CALL_DUMMY_LOCATION != AT_ENTRY_POINT
+ sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET;
+#else
+ sal.pc = entry_point_address ();
+#endif
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ /* Set up a FRAME for the dummy frame so we can pass it to
+ set_momentary_breakpoint. We need to give the breakpoint a
+ frame in case there is only one copy of the dummy (e.g.
+ CALL_DUMMY_LOCATION == AFTER_TEXT_END). */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), sal.pc));
+
+ /* If defined, CALL_DUMMY_BREAKPOINT_OFFSET is where we need to put
+ a breakpoint instruction. If not, the call dummy already has the
+ breakpoint instruction in it.
+
+ addr is the address of the call dummy plus the CALL_DUMMY_START_OFFSET,
+ so we need to subtract the CALL_DUMMY_START_OFFSET. */
+ bpt = set_momentary_breakpoint (sal,
+ get_current_frame (),
+ bp_call_dummy);
+ bpt->disposition = delete;
+
+ /* If all error()s out of proceed ended up calling normal_stop (and
+ perhaps they should; it already does in the special case of error
+ out of resume()), then we wouldn't need this. */
+ make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat);
+ }
+#endif /* CALL_DUMMY_BREAKPOINT_OFFSET. */
+
+ proceed_to_finish = 1; /* We want stop_registers, please... */
+ proceed (addr, 0, 0);
+
+ discard_cleanups (old_cleanups);
+
+ if (!stop_stack_dummy)
+ return 1;
+
+ /* On return, the stack dummy has been popped already. */
+
+ memcpy (buffer, stop_registers, sizeof stop_registers);
+ return 0;
+}
+
+/* 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 */
+
+/* ARGSUSED */
+static 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)
+ {
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
+
+ if (msymbol == NULL)
+ error ("Execution is not within a known function.");
+
+ step_range_start = SYMBOL_VALUE_ADDRESS (msymbol);
+ 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);
+}
+
+static 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);
+}
+
+/* "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;
+ struct breakpoint *breakpoint;
+ struct cleanup *old_chain;
+
+ if (arg)
+ error ("The \"finish\" command does not take any arguments.");
+ if (!target_has_execution)
+ error ("The program is not running.");
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+
+ 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;
+
+ breakpoint = set_momentary_breakpoint (sal, frame, bp_finish);
+
+ old_chain = make_cleanup(delete_breakpoint, breakpoint);
+
+ /* Find the function we will return from. */
+
+ fi = get_frame_info (selected_frame);
+ function = find_pc_function (fi->pc);
+
+ /* Print info on the selected frame, including level number
+ but not source. */
+ if (from_tty)
+ {
+ printf_filtered ("Run till exit from ");
+ print_stack_frame (selected_frame, selected_frame_level, 0);
+ }
+
+ proceed_to_finish = 1; /* We want stop_registers, please... */
+ proceed ((CORE_ADDR) -1, -1, 0);
+
+ /* Did we stop at our breakpoint? */
+ if (bpstat_find_breakpoint(stop_bpstat, breakpoint) != NULL
+ && 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, NULL),
+ funcaddr,
+ value_type,
+ BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))));
+
+ printf_filtered ("Value returned is $%d = ", record_latest_value (val));
+ value_print (val, stdout, 0, Val_no_prettyprint);
+ printf_filtered ("\n");
+ }
+ do_cleanups(old_chain);
+}
+
+/* ARGSUSED */
+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_filtered ("The program being debugged is not being run.\n");
+ return;
+ }
+
+ target_files_info ();
+ printf_filtered ("Program stopped at %s.\n",
+ local_hex_string((unsigned long) stop_pc));
+ if (stop_step)
+ printf_filtered ("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_filtered ("It stopped at a breakpoint that has since been deleted.\n");
+ else
+ printf_filtered ("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
+ char *signame = strsigno (stop_signal);
+ printf_filtered ("It stopped with signal ");
+ if (signame == NULL)
+ printf_filtered ("%d", stop_signal);
+ else
+ /* Do we need to print the number as well as the name? */
+ printf_filtered ("%s (%d)", signame, stop_signal);
+ printf_filtered (", %s.\n", safe_strsignal (stop_signal));
+#endif
+ }
+
+ if (!from_tty)
+ printf_filtered ("Type \"info stack\" or \"info registers\" for more information.\n");
+}
+
+static void
+environment_info (var, from_tty)
+ char *var;
+ int from_tty;
+{
+ if (var)
+ {
+ register char *val = get_in_environ (inferior_environ, var);
+ if (val)
+ {
+ puts_filtered (var);
+ puts_filtered (" = ");
+ puts_filtered (val);
+ puts_filtered ("\n");
+ }
+ else
+ {
+ puts_filtered ("Environment variable \"");
+ puts_filtered (var);
+ puts_filtered ("\" not defined.\n");
+ }
+ }
+ else
+ {
+ register char **vector = environ_vector (inferior_environ);
+ while (*vector)
+ {
+ puts_filtered (*vector++);
+ puts_filtered ("\n");
+ }
+ }
+}
+
+static void
+set_environment_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ 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, walk forward over the spaces til we see a nonspace
+ (possibly the equals). */
+ if (p > val)
+ while (*val == ' ')
+ val++;
+
+ /* Now if the = is after the char following the spaces,
+ take the char following the spaces. */
+ if (p > val)
+ p = val - 1;
+ }
+ 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_filtered ("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) */
+
+static const char path_var_name[] = "PATH";
+
+/* ARGSUSED */
+static void
+path_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ puts_filtered ("Executable and object file path: ");
+ puts_filtered (get_in_environ (inferior_environ, path_var_name));
+ puts_filtered ("\n");
+}
+
+/* Add zero or more directories to the front of the execution path. */
+
+static 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, &exec_path);
+ set_in_environ (inferior_environ, path_var_name, exec_path);
+ free (exec_path);
+ if (from_tty)
+ path_info ((char *)NULL, from_tty);
+}
+
+/* This routine is getting awfully cluttered with #if's. It's probably
+ time to turn this into READ_PC and define it in the tm.h file.
+ Ditto for write_pc. */
+
+CORE_ADDR
+read_pc ()
+{
+#ifdef TARGET_READ_PC
+ return TARGET_READ_PC ();
+#else
+ return ADDR_BITS_REMOVE ((CORE_ADDR) read_register (PC_REGNUM));
+#endif
+}
+
+void
+write_pc (val)
+ CORE_ADDR val;
+{
+#ifdef TARGET_WRITE_PC
+ TARGET_WRITE_PC (val);
+#else
+ write_register (PC_REGNUM, (long) val);
+#ifdef NPC_REGNUM
+ write_register (NPC_REGNUM, (long) val + 4);
+#ifdef NNPC_REGNUM
+ write_register (NNPC_REGNUM, (long) val + 8);
+#endif
+#endif
+#endif
+}
+
+/* Cope with strage ways of getting to the stack and frame pointers */
+
+CORE_ADDR
+read_sp ()
+{
+#ifdef TARGET_READ_SP
+ return TARGET_READ_SP ();
+#else
+ return read_register (SP_REGNUM);
+#endif
+}
+
+void
+write_sp (val)
+ CORE_ADDR val;
+{
+#ifdef TARGET_WRITE_SP
+ TARGET_WRITE_SP (val);
+#else
+ write_register (SP_REGNUM, val);
+#endif
+}
+
+
+CORE_ADDR
+read_fp ()
+{
+#ifdef TARGET_READ_FP
+ return TARGET_READ_FP ();
+#else
+ return read_register (FP_REGNUM);
+#endif
+}
+
+void
+write_fp (val)
+ CORE_ADDR val;
+{
+#ifdef TARGET_WRITE_FP
+ TARGET_WRITE_FP (val);
+#else
+ write_register (FP_REGNUM, val);
+#endif
+}
+
+const char * const reg_names[] = REGISTER_NAMES;
+
+/* Print out the machine register regnum. If regnum is -1,
+ print all registers (fpregs == 1) or all non-float registers
+ (fpregs == 0).
+
+ 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 MIPS 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, fp)
+ to provide that format. */
+
+#if !defined (DO_REGISTERS_INFO)
+#define DO_REGISTERS_INFO(regnum, fp) do_registers_info(regnum, fp)
+static void
+do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ register int i;
+
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+
+ /* Decide between printing all regs, nonfloat regs, or specific reg. */
+ if (regnum == -1) {
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT && !fpregs)
+ continue;
+ } else {
+ if (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;
+ }
+
+ REGISTER_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, fpregs)
+ char *addr_exp;
+ int fpregs;
+{
+ int regnum;
+ register char *end;
+
+ if (!target_has_registers)
+ error ("The program has no registers now.");
+
+ if (!addr_exp)
+ {
+ DO_REGISTERS_INFO(-1, fpregs);
+ return;
+ }
+
+ do
+ {
+ if (addr_exp[0] == '$')
+ addr_exp++;
+ end = addr_exp;
+ while (*end != '\0' && *end != ' ' && *end != '\t')
+ ++end;
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ if (!strncmp (addr_exp, reg_names[regnum], end - addr_exp)
+ && strlen (reg_names[regnum]) == end - addr_exp)
+ goto found;
+ if (*addr_exp >= '0' && *addr_exp <= '9')
+ regnum = atoi (addr_exp); /* Take a number */
+ if (regnum >= NUM_REGS) /* Bad name, or bad number */
+ error ("%.*s: invalid register", end - addr_exp, addr_exp);
+
+found:
+ DO_REGISTERS_INFO(regnum, fpregs);
+
+ addr_exp = end;
+ while (*addr_exp == ' ' || *addr_exp == '\t')
+ ++addr_exp;
+ } while (*addr_exp != '\0');
+}
+
+static void
+all_registers_info (addr_exp, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+ registers_info (addr_exp, 1);
+}
+
+static void
+nofp_registers_info (addr_exp, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+ registers_info (addr_exp, 0);
+}
+
+/*
+ * 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 debugging it.
+ and wait for the trace-trap that results from attaching. */
+
+void
+attach_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat (); /* Not for the faint of heart */
+
+ if (target_has_execution)
+ {
+ if (query ("A program is being debugged already. Kill it? "))
+ target_kill ();
+ else
+ error ("Not killed.");
+ }
+
+ target_attach (args, from_tty);
+
+ /* 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 ();
+
+ /* Set up execution context to know that we should return from
+ wait_for_inferior as soon as the target reports a stop. */
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+
+ wait_for_inferior ();
+
+#ifdef SOLIB_ADD
+ /* Add shared library symbols from the newly attached process, if any. */
+ SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
+#endif
+
+ 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
+detach_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat (); /* Not for the faint of heart */
+ target_detach (args, from_tty);
+}
+
+/* ARGSUSED */
+static void
+float_info (addr_exp, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+#ifdef FLOAT_INFO
+ FLOAT_INFO;
+#else
+ printf_filtered ("No floating point info available for this processor.\n");
+#endif
+}
+
+/* ARGSUSED */
+static void
+unset_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_filtered ("\"unset\" must be followed by the name of an unset subcommand.\n");
+ help_list (unsetlist, "unset ", -1, stdout);
+}
+
+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;
+
+ add_prefix_cmd ("unset", no_class, unset_command,
+ "Complement to certain \"set\" commands",
+ &unsetlist, "unset ", 0, &cmdlist);
+
+ 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.",
+ &unsetlist);
+ 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.");
+
+ c = add_cmd ("paths", no_class, 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.", &showlist);
+ c->completer = noop_completer;
+
+ 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\
+which means to set the ignore count of that breakpoint to N - 1 (so that\n\
+the 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", nofp_registers_info,
+ "List of integer registers and their contents, for selected stack frame.\n\
+Register name as argument means describe only that register.");
+
+ add_info ("all-registers", all_registers_info,
+"List of all 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/gnu/usr.bin/gdb/gdb/inferior.h b/gnu/usr.bin/gdb/gdb/inferior.h
new file mode 100644
index 000000000000..0f5499a3c6ba
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/inferior.h
@@ -0,0 +1,401 @@
+/* Variables that describe the inferior process running under GDB:
+ Where it is, why it stopped, and how to step it.
+ Copyright 1986, 1989, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (INFERIOR_H)
+#define INFERIOR_H 1
+
+/* 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 stop_signal;
+ CORE_ADDR 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];
+
+ /* These are here because if call_function_by_hand has written some
+ registers and then decides to call error(), we better not have changed
+ any registers. */
+ char registers[REGISTER_BYTES];
+
+ int breakpoint_proceeded;
+ int restore_stack_info;
+ int proceed_to_finish;
+};
+
+extern void
+save_inferior_status PARAMS ((struct inferior_status *, int));
+
+extern void
+restore_inferior_status PARAMS ((struct 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[];
+
+/* Array of validity bits (one per register). Nonzero at position XXX_REGNUM
+ means that `registers' contains a valid copy of inferior register XXX. */
+
+extern char register_valid[NUM_REGS];
+
+extern void
+clear_proceed_status PARAMS ((void));
+
+extern void
+proceed PARAMS ((CORE_ADDR, int, int));
+
+extern void
+kill_inferior PARAMS ((void));
+
+extern void
+generic_mourn_inferior PARAMS ((void));
+
+extern void
+terminal_ours PARAMS ((void));
+
+extern int run_stack_dummy PARAMS ((CORE_ADDR, char [REGISTER_BYTES]));
+
+extern CORE_ADDR
+read_pc PARAMS ((void));
+
+extern void
+write_pc PARAMS ((CORE_ADDR));
+
+extern CORE_ADDR
+read_sp PARAMS ((void));
+
+extern void
+write_sp PARAMS ((CORE_ADDR));
+
+extern CORE_ADDR
+read_fp PARAMS ((void));
+
+extern void
+write_fp PARAMS ((CORE_ADDR));
+
+extern void
+wait_for_inferior PARAMS ((void));
+
+extern void
+init_wait_for_inferior PARAMS ((void));
+
+extern void
+close_exec_file PARAMS ((void));
+
+extern void
+reopen_exec_file PARAMS ((void));
+
+/* The `resume' routine should only be called in special circumstances.
+ Normally, use `proceed', which handles a lot of bookkeeping. */
+extern void
+resume PARAMS ((int, int));
+
+/* From misc files */
+
+extern void
+store_inferior_registers PARAMS ((int));
+
+extern void
+fetch_inferior_registers PARAMS ((int));
+
+extern void
+solib_create_inferior_hook PARAMS ((void));
+
+extern void
+child_terminal_info PARAMS ((char *, int));
+
+extern void
+term_info PARAMS ((char *, int));
+
+extern void
+terminal_ours_for_output PARAMS ((void));
+
+extern void
+terminal_inferior PARAMS ((void));
+
+extern void
+terminal_init_inferior PARAMS ((void));
+
+/* From infptrace.c */
+
+extern int
+attach PARAMS ((int));
+
+void
+detach PARAMS ((int));
+
+extern void
+child_resume PARAMS ((int, int, int));
+
+#ifndef PTRACE_ARG3_TYPE
+#define PTRACE_ARG3_TYPE int /* Correct definition for most systems. */
+#endif
+
+extern int
+call_ptrace PARAMS ((int, int, PTRACE_ARG3_TYPE, int));
+
+/* From procfs.c */
+
+extern int
+proc_iterate_over_mappings PARAMS ((int (*) (int, CORE_ADDR)));
+
+/* From fork-child.c */
+
+extern void
+fork_inferior PARAMS ((char *, char *, char **,
+ void (*) (void),
+ void (*) (int)));
+
+/* From inflow.c */
+
+extern void
+new_tty_prefork PARAMS ((char *));
+
+extern int gdb_has_a_terminal PARAMS ((void));
+
+/* From infrun.c */
+
+extern void
+start_remote PARAMS ((void));
+
+extern void
+normal_stop PARAMS ((void));
+
+extern int
+signal_stop_state PARAMS ((int));
+
+extern int
+signal_print_state PARAMS ((int));
+
+extern int
+signal_pass_state PARAMS ((int));
+
+/* From infcmd.c */
+
+extern void
+tty_command PARAMS ((char *, int));
+
+extern void
+attach_command PARAMS ((char *, int));
+
+/* 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.
+
+ If step_range_start and step_range_end are both 1, it means to step for
+ a single instruction (FIXME: it might clean up wait_for_inferior in a
+ minor way if this were changed to the address of the instruction and
+ that address plus one. But maybe not.). */
+
+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 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?). */
+
+extern int stop_soon_quietly;
+
+/* 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 the child process in inferior_pid was attached rather
+ than forked. */
+
+extern int attach_flag;
+
+/* 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)
+# if defined (SIGTRAMP_START)
+# define IN_SIGTRAMP(pc, name) \
+ ((pc) >= SIGTRAMP_START \
+ && (pc) < SIGTRAMP_END \
+ )
+# else
+# define IN_SIGTRAMP(pc, name) \
+ (name && STREQ ("_sigtramp", name))
+# endif
+#endif
+
+/* Possible values for CALL_DUMMY_LOCATION. */
+#define ON_STACK 1
+#define BEFORE_TEXT_END 2
+#define AFTER_TEXT_END 3
+#define AT_ENTRY_POINT 4
+
+#if !defined (CALL_DUMMY_LOCATION)
+#define CALL_DUMMY_LOCATION ON_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
+extern CORE_ADDR text_end;
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((pc) >= text_end - CALL_DUMMY_LENGTH \
+ && (pc) <= text_end + DECR_PC_AFTER_BREAK)
+#endif /* Before text_end. */
+
+#if CALL_DUMMY_LOCATION == AFTER_TEXT_END
+extern CORE_ADDR text_end;
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((pc) >= text_end \
+ && (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK)
+#endif /* After text_end. */
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+/* Is the PC in a call dummy? SP and FRAME_ADDRESS are the bottom and
+ top of the stack frame which we are checking, where "bottom" and
+ "top" refer to some section of memory which contains the code for
+ the call dummy. Calls to this macro assume that the contents of
+ SP_REGNUM and FP_REGNUM (or the saved values thereof), respectively,
+ are the things to pass.
+
+ This won't work on the 29k, where SP_REGNUM and FP_REGNUM don't
+ have that meaning, but the 29k doesn't use ON_STACK. This could be
+ fixed by generalizing this scheme, perhaps by passing in a frame
+ and adding a few fields, at least on machines which need them for
+ PC_IN_CALL_DUMMY.
+
+ Something simpler, like checking for the stack segment, doesn't work,
+ since various programs (threads implementations, gcc nested function
+ stubs, etc) may either allocate stack frames in another segment, or
+ allocate other kinds of code on the stack. */
+
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((sp) INNER_THAN (pc) && (frame_address != 0) && (pc) INNER_THAN (frame_address))
+#endif /* On stack. */
+
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+extern CORE_ADDR
+entry_point_address PARAMS ((void));
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((pc) >= entry_point_address () \
+ && (pc) <= (entry_point_address () + DECR_PC_AFTER_BREAK))
+#endif /* At entry point. */
+#endif /* No PC_IN_CALL_DUMMY. */
+
+#endif /* !defined (INFERIOR_H) */
diff --git a/gnu/usr.bin/gdb/gdb/inflow.c b/gnu/usr.bin/gdb/gdb/inflow.c
new file mode 100644
index 000000000000..be0b43ba672e
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/inflow.c
@@ -0,0 +1,662 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "command.h"
+#include "signals.h"
+#include "serial.h"
+#include "terminal.h"
+#include "target.h"
+
+#include <signal.h>
+#include <fcntl.h>
+
+#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY) && !defined (__GO32__)
+#define HAVE_SGTTY
+#endif
+
+#if defined (HAVE_TERMIOS)
+#include <termios.h>
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_TERMIOS
+#define PROCESS_GROUP_TYPE pid_t
+#endif
+
+#ifdef HAVE_SGTTY
+#ifdef SHORT_PGRP
+/* This is only used for the ultra. Does it have pid_t? */
+#define PROCESS_GROUP_TYPE short
+#else
+#define PROCESS_GROUP_TYPE int
+#endif
+#endif /* sgtty */
+
+static void
+kill_command PARAMS ((char *, int));
+
+static void
+terminal_ours_1 PARAMS ((int));
+
+/* Nonzero if we are debugging an attached outside process
+ rather than an inferior. */
+
+int attach_flag;
+
+
+/* Record terminal status separately for debugger and inferior. */
+
+static serial_t stdin_serial;
+
+/* TTY state for the inferior. We save it whenever the inferior stops, and
+ restore it when it resumes. */
+static serial_ttystate inferior_ttystate;
+
+/* Our own tty state, which we restore every time we need to deal with the
+ terminal. We only set it once, when GDB first starts. The settings of
+ flags which readline saves and restores and unimportant. */
+static serial_ttystate our_ttystate;
+
+/* fcntl flags for us and the inferior. Saved and restored just like
+ {our,inferior}_ttystate. */
+static int tflags_inferior;
+static int tflags_ours;
+
+#ifdef PROCESS_GROUP_TYPE
+/* Process group for us and the inferior. Saved and restored just like
+ {our,inferior}_ttystate. */
+PROCESS_GROUP_TYPE our_process_group;
+PROCESS_GROUP_TYPE inferior_process_group;
+#endif
+
+/* While the inferior is running, we want SIGINT and SIGQUIT to go to the
+ inferior only. If we have job control, that takes care of it. If not,
+ we save our handlers in these two variables and set SIGINT and SIGQUIT
+ to SIG_IGN. */
+static void (*sigint_ours) ();
+static void (*sigquit_ours) ();
+
+/* The name of the tty (from the `tty' command) that we gave to the inferior
+ when it was last started. */
+
+static char *inferior_thisrun_terminal;
+
+/* Nonzero if our terminal settings are in effect. Zero if the
+ inferior's settings are in effect. Ignored if !gdb_has_a_terminal
+ (). */
+
+static int terminal_is_ours;
+
+enum {yes, no, have_not_checked} gdb_has_a_terminal_flag = have_not_checked;
+
+/* Does GDB have a terminal (on stdin)? */
+int
+gdb_has_a_terminal ()
+{
+ switch (gdb_has_a_terminal_flag)
+ {
+ case yes:
+ return 1;
+ case no:
+ return 0;
+ case have_not_checked:
+ /* Get all the current tty settings (including whether we have a tty at
+ all!). Can't do this in _initialize_inflow because SERIAL_FDOPEN
+ won't work until the serial_ops_list is initialized. */
+
+#ifdef F_GETFL
+ tflags_ours = fcntl (0, F_GETFL, 0);
+#endif
+
+ gdb_has_a_terminal_flag = no;
+ stdin_serial = SERIAL_FDOPEN (0);
+ if (stdin_serial != NULL)
+ {
+ our_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
+
+ if (our_ttystate != NULL)
+ {
+ gdb_has_a_terminal_flag = yes;
+#ifdef HAVE_TERMIOS
+ our_process_group = tcgetpgrp (0);
+#endif
+#ifdef HAVE_SGTTY
+ ioctl (0, TIOCGPGRP, &our_process_group);
+#endif
+ }
+ }
+
+ return gdb_has_a_terminal_flag == yes;
+ }
+}
+
+/* Macro for printing errors from ioctl operations */
+
+#define OOPSY(what) \
+ if (result == -1) \
+ fprintf(stderr, "[%s failed in terminal_inferior: %s]\n", \
+ what, strerror (errno))
+
+static void terminal_ours_1 PARAMS ((int));
+
+/* Initialize the terminal settings we record for the inferior,
+ before we actually run the inferior. */
+
+void
+terminal_init_inferior ()
+{
+ if (gdb_has_a_terminal ())
+ {
+ /* We could just as well copy our_ttystate (if we felt like adding
+ a new function SERIAL_COPY_TTY_STATE). */
+ if (inferior_ttystate)
+ free (inferior_ttystate);
+ inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
+#ifdef PROCESS_GROUP_TYPE
+ inferior_process_group = inferior_pid;
+#endif
+
+ /* Make sure that next time we call terminal_inferior (which will be
+ before the program runs, as it needs to be), we install the new
+ process group. */
+ 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 (gdb_has_a_terminal () && terminal_is_ours
+ && inferior_thisrun_terminal == 0)
+ {
+ int result;
+
+#ifdef F_GETFL
+ /* Is there a reason this is being done twice? It happens both
+ places we use F_SETFL, so I'm inclined to think perhaps there
+ is some reason, however perverse. Perhaps not though... */
+ result = fcntl (0, F_SETFL, tflags_inferior);
+ result = fcntl (0, F_SETFL, tflags_inferior);
+ OOPSY ("fcntl F_SETFL");
+#endif
+
+ /* Because we were careful to not change in or out of raw mode in
+ terminal_ours, we will not change in our out of raw mode with
+ this call, so we don't flush any input. */
+ result = SERIAL_SET_TTY_STATE (stdin_serial, inferior_ttystate);
+ OOPSY ("setting tty state");
+
+ if (!job_control)
+ {
+ sigint_ours = (void (*) ()) signal (SIGINT, SIG_IGN);
+ sigquit_ours = (void (*) ()) signal (SIGQUIT, SIG_IGN);
+ }
+
+ /* If attach_flag is set, we don't know whether we are sharing a
+ terminal with the inferior or not. (attaching a process
+ without a terminal is one case where we do not; attaching a
+ process which we ran from the same shell as GDB via `&' is
+ one case where we do, I think (but perhaps this is not
+ `sharing' in the sense that we need to save and restore tty
+ state)). I don't know if there is any way to tell whether we
+ are sharing a terminal. So what we do is to go through all
+ the saving and restoring of the tty state, but ignore errors
+ setting the process group, which will happen if we are not
+ sharing a terminal). */
+
+ if (job_control)
+ {
+#ifdef HAVE_TERMIOS
+ result = tcsetpgrp (0, inferior_process_group);
+ if (!attach_flag)
+ OOPSY ("tcsetpgrp");
+#endif
+
+#ifdef HAVE_SGTTY
+ result = ioctl (0, TIOCSPGRP, &inferior_process_group);
+ if (!attach_flag)
+ OOPSY ("TIOCSPGRP");
+#endif
+ }
+
+ }
+ 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);
+}
+
+/* output_only is not used, and should not be used unless we introduce
+ separate terminal_is_ours and terminal_is_ours_for_output
+ flags. */
+
+static void
+terminal_ours_1 (output_only)
+ int output_only;
+{
+ /* 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. Checking gdb_has_a_terminal
+ avoids attempting all the ioctl's when running in batch. */
+ if (inferior_thisrun_terminal != 0 || gdb_has_a_terminal () == 0)
+ return;
+
+ if (!terminal_is_ours)
+ {
+ /* Ignore this signal since it will happen when we try to set the
+ pgrp. */
+ void (*osigttou) ();
+ int result;
+
+ terminal_is_ours = 1;
+
+#ifdef SIGTTOU
+ if (job_control)
+ osigttou = (void (*) ()) signal (SIGTTOU, SIG_IGN);
+#endif
+
+ if (inferior_ttystate)
+ free (inferior_ttystate);
+ inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
+#ifdef HAVE_TERMIOS
+ inferior_process_group = tcgetpgrp (0);
+#endif
+#ifdef HAVE_SGTTY
+ ioctl (0, TIOCGPGRP, &inferior_process_group);
+#endif
+
+ /* Here we used to set ICANON in our ttystate, but I believe this
+ was an artifact from before when we used readline. Readline sets
+ the tty state when it needs to. */
+
+ /* Set tty state to our_ttystate. We don't change in our out of raw
+ mode, to avoid flushing input. We need to do the same thing
+ regardless of output_only, because we don't have separate
+ terminal_is_ours and terminal_is_ours_for_output flags. It's OK,
+ though, since readline will deal with raw mode when/if it needs to.
+ */
+ SERIAL_NOFLUSH_SET_TTY_STATE (stdin_serial, our_ttystate,
+ inferior_ttystate);
+
+ if (job_control)
+ {
+#ifdef HAVE_TERMIOS
+ result = tcsetpgrp (0, our_process_group);
+#if 0
+ /* This fails on Ultrix with EINVAL if you run the testsuite
+ in the background with nohup, and then log out. GDB never
+ used to check for an error here, so perhaps there are other
+ such situations as well. */
+ if (result == -1)
+ fprintf (stderr, "[tcsetpgrp failed in terminal_ours: %s]\n",
+ strerror (errno));
+#endif
+#endif /* termios */
+
+#ifdef HAVE_SGTTY
+ result = ioctl (0, TIOCSPGRP, &our_process_group);
+#endif
+ }
+
+#ifdef SIGTTOU
+ if (job_control)
+ signal (SIGTTOU, osigttou);
+#endif
+
+ if (!job_control)
+ {
+ signal (SIGINT, sigint_ours);
+ signal (SIGQUIT, sigquit_ours);
+ }
+
+#ifdef F_GETFL
+ tflags_inferior = fcntl (0, F_GETFL, 0);
+
+ /* Is there a reason this is being done twice? It happens both
+ places we use F_SETFL, so I'm inclined to think perhaps there
+ is some reason, however perverse. Perhaps not though... */
+ result = fcntl (0, F_SETFL, tflags_ours);
+ result = fcntl (0, F_SETFL, tflags_ours);
+#endif
+
+ result = result; /* lint */
+ }
+}
+
+/* ARGSUSED */
+void
+term_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ target_terminal_info (arg, from_tty);
+}
+
+/* ARGSUSED */
+void
+child_terminal_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (!gdb_has_a_terminal ())
+ {
+ printf_filtered ("This GDB does not control a terminal.\n");
+ return;
+ }
+
+ printf_filtered ("Inferior's terminal status (currently saved by GDB):\n");
+
+ /* First the fcntl flags. */
+ {
+ int flags;
+
+ flags = tflags_inferior;
+
+ printf_filtered ("File descriptor flags = ");
+
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+ /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
+ switch (flags & (O_ACCMODE))
+ {
+ case O_RDONLY: printf_filtered ("O_RDONLY"); break;
+ case O_WRONLY: printf_filtered ("O_WRONLY"); break;
+ case O_RDWR: printf_filtered ("O_RDWR"); break;
+ }
+ flags &= ~(O_ACCMODE);
+
+#ifdef O_NONBLOCK
+ if (flags & O_NONBLOCK)
+ printf_filtered (" | O_NONBLOCK");
+ flags &= ~O_NONBLOCK;
+#endif
+
+#if defined (O_NDELAY)
+ /* If O_NDELAY and O_NONBLOCK are defined to the same thing, we will
+ print it as O_NONBLOCK, which is good cause that is what POSIX
+ has, and the flag will already be cleared by the time we get here. */
+ if (flags & O_NDELAY)
+ printf_filtered (" | O_NDELAY");
+ flags &= ~O_NDELAY;
+#endif
+
+ if (flags & O_APPEND)
+ printf_filtered (" | O_APPEND");
+ flags &= ~O_APPEND;
+
+#if defined (O_BINARY)
+ if (flags & O_BINARY)
+ printf_filtered (" | O_BINARY");
+ flags &= ~O_BINARY;
+#endif
+
+ if (flags)
+ printf_filtered (" | 0x%x", flags);
+ printf_filtered ("\n");
+ }
+
+#ifdef PROCESS_GROUP_TYPE
+ printf_filtered ("Process group = %d\n", inferior_process_group);
+#endif
+
+ SERIAL_PRINT_TTY_STATE (stdin_serial, inferior_ttystate);
+}
+
+/* NEW_TTY_PREFORK is called before forking a new child process,
+ so we can record the state of ttys in the child to be formed.
+ TTYNAME is null if we are to share the terminal with gdb;
+ or points to a string containing the name of the desired tty.
+
+ NEW_TTY is called in new child processes under Unix, which will
+ become debugger target processes. This actually switches to
+ the terminal specified in the NEW_TTY_PREFORK call. */
+
+void
+new_tty_prefork (ttyname)
+ char *ttyname;
+{
+ /* Save the name for later, for determining whether we and the child
+ are sharing a tty. */
+ inferior_thisrun_terminal = ttyname;
+}
+
+void
+new_tty ()
+{
+ register int tty;
+
+ if (inferior_thisrun_terminal == 0)
+ return;
+#if !defined(__GO32__)
+#ifdef TIOCNOTTY
+ /* Disconnect the child process from our controlling terminal. On some
+ systems (SVR4 for example), this may cause a SIGTTOU, so temporarily
+ ignore SIGTTOU. */
+ tty = open("/dev/tty", O_RDWR);
+ if (tty > 0)
+ {
+ void (*osigttou) ();
+
+ osigttou = (void (*)()) signal(SIGTTOU, SIG_IGN);
+ ioctl(tty, TIOCNOTTY, 0);
+ close(tty);
+ signal(SIGTTOU, osigttou);
+ }
+#endif
+
+ /* Now open the specified new terminal. */
+
+#ifdef USE_O_NOCTTY
+ tty = open(inferior_thisrun_terminal, O_RDWR | O_NOCTTY);
+#else
+ tty = open(inferior_thisrun_terminal, O_RDWR);
+#endif
+ if (tty == -1)
+ {
+ print_sys_errmsg (inferior_thisrun_terminal, 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);
+#endif /* !go32 */
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+/* ARGSUSED */
+static void
+kill_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ /* Shouldn't this be target_has_execution? FIXME. */
+ if (inferior_pid == 0)
+ error ("The program is not being run.");
+ if (!query ("Kill the program being debugged? "))
+ error ("Not confirmed.");
+ target_kill ();
+
+ init_thread_list(); /* Destroy thread info */
+
+ /* Killing off the inferior can leave us with a core file. If so,
+ print the state we are left in. */
+ if (target_has_stack) {
+ printf_filtered ("In %s,\n", current_target->to_longname);
+ if (selected_frame == NULL)
+ fputs_filtered ("No selected stack frame.\n", stdout);
+ else
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+ }
+}
+
+/* The inferior process has died. Long live the inferior! */
+
+void
+generic_mourn_inferior ()
+{
+ inferior_pid = 0;
+ attach_flag = 0;
+ breakpoint_init_inferior ();
+ registers_changed ();
+
+#ifdef CLEAR_DEFERRED_STORES
+ /* Delete any pending stores to the inferior... */
+ CLEAR_DEFERRED_STORES;
+#endif
+
+ reopen_exec_file ();
+ reinit_frame_cache ();
+
+ /* 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 ();
+}
+
+/* Call set_sigint_trap when you need to pass a signal on to an attached
+ process when handling SIGINT */
+
+/* ARGSUSED */
+static void
+pass_signal (signo)
+ int signo;
+{
+ kill (inferior_pid, SIGINT);
+}
+
+static void (*osig)();
+
+void
+set_sigint_trap()
+{
+ osig = (void (*) ()) signal (SIGINT, pass_signal);
+}
+
+void
+clear_sigint_trap()
+{
+ signal (SIGINT, osig);
+}
+
+
+int job_control;
+
+/* This is here because this is where we figure out whether we (probably)
+ have job control. Just using job_control only does part of it because
+ setpgid or setpgrp might not exist on a system without job control.
+ It might be considered misplaced (on the other hand, process groups and
+ job control are closely related to ttys).
+
+ For a more clean implementation, in libiberty, put a setpgid which merely
+ calls setpgrp and a setpgrp which does nothing (any system with job control
+ will have one or the other). */
+int
+gdb_setpgid ()
+{
+ int retval = 0;
+ if (job_control)
+ {
+#if defined (NEED_POSIX_SETPGID) || defined (HAVE_TERMIOS)
+ /* Do all systems with termios have setpgid? I hope so. */
+ /* setpgid (0, 0) is supposed to work and mean the same thing as
+ this, but on Ultrix 4.2A it fails with EPERM (and
+ setpgid (getpid (), getpid ()) succeeds). */
+ retval = setpgid (getpid (), getpid ());
+#else
+#if defined (TIOCGPGRP)
+#if defined(USG) && !defined(SETPGRP_ARGS)
+ retval = setpgrp ();
+#else
+ retval = setpgrp (getpid (), getpid ());
+#endif /* USG */
+#endif /* TIOCGPGRP. */
+#endif /* NEED_POSIX_SETPGID */
+ }
+ return retval;
+}
+
+void
+_initialize_inflow ()
+{
+ add_info ("terminal", term_info,
+ "Print inferior's saved terminal status.");
+
+ add_com ("kill", class_run, kill_command,
+ "Kill execution of program being debugged.");
+
+ inferior_pid = 0;
+
+ terminal_is_ours = 1;
+
+ /* OK, figure out whether we have job control. If neither termios nor
+ sgtty (i.e. termio or go32), leave job_control 0. */
+
+#if defined (HAVE_TERMIOS)
+ /* Do all systems with termios have the POSIX way of identifying job
+ control? I hope so. */
+#ifdef _POSIX_JOB_CONTROL
+ job_control = 1;
+#else
+ job_control = sysconf (_SC_JOB_CONTROL);
+#endif
+#endif /* termios */
+
+#ifdef HAVE_SGTTY
+#ifdef TIOCGPGRP
+ job_control = 1;
+#else
+ job_control = 0;
+#endif /* TIOCGPGRP */
+#endif /* sgtty */
+}
diff --git a/gnu/usr.bin/gdb/gdb/infptrace.c b/gnu/usr.bin/gdb/gdb/infptrace.c
new file mode 100644
index 000000000000..a152d673a5df
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/infptrace.c
@@ -0,0 +1,436 @@
+/* Low level Unix child interface to ptrace, for GDB when running under Unix.
+ Copyright 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.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>
+
+#ifndef NO_PTRACE_H
+#ifdef PTRACE_IN_WRONG_PLACE
+#include <ptrace.h>
+#else
+#include <sys/ptrace.h>
+#endif
+#endif /* NO_PTRACE_H */
+
+#if !defined (PT_KILL)
+#define PT_KILL 8
+#endif
+
+#if !defined (PT_STEP)
+#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_READ_D 2
+#define PT_WRITE_I 4
+#define PT_WRITE_D 5
+#endif /* No PT_STEP. */
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+#ifndef PT_DETACH
+#define PT_DETACH PTRACE_DETACH
+#endif
+
+#include "gdbcore.h"
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#if 0
+/* Don't think this is used anymore. On the sequent (not sure whether it's
+ dynix or ptx or both), it is included unconditionally by sys/user.h and
+ not protected against multiple inclusion. */
+#include <sys/stat.h>
+#endif
+
+#if !defined (FETCH_INFERIOR_REGISTERS)
+#include <sys/user.h> /* Probably need to poke the user structure */
+#if defined (KERNEL_U_ADDR_BSD)
+#include <a.out.h> /* For struct nlist */
+#endif /* KERNEL_U_ADDR_BSD. */
+#endif /* !FETCH_INFERIOR_REGISTERS */
+
+
+/* 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;
+ PTRACE_ARG3_TYPE addr;
+ int data;
+{
+ return ptrace (request, pid, addr, data
+#if defined (FIVE_ARG_PTRACE)
+ /* Deal with HPUX 8.0 braindamage. We never use the
+ calls which require the fifth argument. */
+ , 0
+#endif
+ );
+}
+
+#if defined (DEBUG_PTRACE) || defined (FIVE_ARG_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
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ /* ptrace PT_KILL only works if process is stopped!!! So stop it with
+ a real signal first, if we can. */
+ kill (inferior_pid, SIGKILL);
+ ptrace (PT_KILL, inferior_pid, (PTRACE_ARG3_TYPE) 0, 0);
+ wait ((int *)0);
+ 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 (pid, step, signal)
+ int pid;
+ int step;
+ int signal;
+{
+ errno = 0;
+
+ if (pid == -1)
+ pid = inferior_pid;
+
+ /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace 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 this system does not support PT_STEP, a higher level function will
+ have called single_step() to transmute the step request into a
+ continue request (by setting breakpoints on all possible successor
+ instructions), so we don't have to worry about that here. */
+
+ if (step)
+ ptrace (PT_STEP, pid, (PTRACE_ARG3_TYPE) 1, signal);
+ else
+ ptrace (PT_CONTINUE, pid, (PTRACE_ARG3_TYPE) 1, signal);
+
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#ifdef ATTACH_DETACH
+/* Start debugging the process whose number is PID. */
+int
+attach (pid)
+ int pid;
+{
+ errno = 0;
+ ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 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, (PTRACE_ARG3_TYPE) 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+ attach_flag = 0;
+}
+#endif /* ATTACH_DETACH */
+
+/* Default the type of the ptrace transfer to int. */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE int
+#endif
+
+#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 (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, \
+ (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
+ - KERNEL_U_ADDR
+#endif
+
+/* Registers we shouldn't try to fetch. */
+#if !defined (CANNOT_FETCH_REGISTER)
+#define CANNOT_FETCH_REGISTER(regno) 0
+#endif
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ char mess[128]; /* For messages */
+ register int i;
+
+ /* Offset of registers within the u area. */
+ unsigned int offset;
+
+ if (CANNOT_FETCH_REGISTER (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ *(PTRACE_XFER_TYPE *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* 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). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+ register int i;
+
+ unsigned int offset = U_REGS_OFFSET;
+
+ if (regno >= 0)
+ {
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ regaddr += sizeof(PTRACE_XFER_TYPE);
+ }
+ }
+ 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(PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ regaddr += sizeof(PTRACE_XFER_TYPE);
+ }
+ }
+ }
+}
+#endif /* !defined (FETCH_INFERIOR_REGISTERS). */
+
+/* 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, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (PTRACE_XFER_TYPE);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+ / sizeof (PTRACE_XFER_TYPE);
+ /* Allocate buffer of that many longwords. */
+ register PTRACE_XFER_TYPE *buffer
+ = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = ptrace (PT_READ_I, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ 0);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = ptrace (PT_READ_I, inferior_pid,
+ ((PTRACE_ARG3_TYPE)
+ (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE))),
+ 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ myaddr,
+ len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_D, inferior_pid, (PTRACE_ARG3_TYPE) 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, (PTRACE_ARG3_TYPE) addr,
+ buffer[i]);
+ }
+ if (errno)
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ buffer[i] = ptrace (PT_READ_I, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0);
+ if (errno)
+ return 0;
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr,
+ (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ len);
+ }
+ return len;
+}
diff --git a/gnu/usr.bin/gdb/gdb/infrun.c b/gnu/usr.bin/gdb/gdb/infrun.c
new file mode 100644
index 000000000000..9266c31caf15
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/infrun.c
@@ -0,0 +1,1848 @@
+/* Target-struct-independent code to start (run) and stop an inferior process.
+ Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <string.h>
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "breakpoint.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#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
+
+/* Prototypes for local functions */
+
+static void
+signals_info PARAMS ((char *, int));
+
+static void
+handle_command PARAMS ((char *, int));
+
+static void
+sig_print_info PARAMS ((int));
+
+static void
+sig_print_header PARAMS ((void));
+
+static void
+resume_cleanups PARAMS ((int));
+
+static int
+hook_stop_stub PARAMS ((char *));
+
+/* GET_LONGJMP_TARGET returns the PC at which longjmp() will resume the
+ program. It needs to examine the jmp_buf argument and extract the PC
+ from it. The return value is non-zero on success, zero otherwise. */
+#ifndef GET_LONGJMP_TARGET
+#define GET_LONGJMP_TARGET(PC_ADDR) 0
+#endif
+
+
+/* Some machines have trampoline code that sits between function callers
+ and the actual functions themselves. If this machine doesn't have
+ such things, disable their processing. */
+#ifndef SKIP_TRAMPOLINE_CODE
+#define SKIP_TRAMPOLINE_CODE(pc) 0
+#endif
+
+/* For SVR4 shared libraries, each call goes through a small piece of
+ trampoline code in the ".init" section. IN_SOLIB_TRAMPOLINE evaluates
+ to nonzero if we are current stopped in one of these. */
+#ifndef IN_SOLIB_TRAMPOLINE
+#define IN_SOLIB_TRAMPOLINE(pc,name) 0
+#endif
+
+/* On some systems, the PC may be left pointing at an instruction that won't
+ actually be executed. This is usually indicated by a bit in the PSW. If
+ we find ourselves in such a state, then we step the target beyond the
+ nullified instruction before returning control to the user so as to avoid
+ confusion. */
+
+#ifndef INSTRUCTION_NULLIFIED
+#define INSTRUCTION_NULLIFIED 0
+#endif
+
+/* Tables of how to react to signals; the user sets them. */
+
+static unsigned char *signal_stop;
+static unsigned char *signal_print;
+static unsigned char *signal_program;
+
+#define SET_SIGS(nsigs,sigs,flags) \
+ do { \
+ int signum = (nsigs); \
+ while (signum-- > 0) \
+ if ((sigs)[signum]) \
+ (flags)[signum] = 1; \
+ } while (0)
+
+#define UNSET_SIGS(nsigs,sigs,flags) \
+ do { \
+ int signum = (nsigs); \
+ while (signum-- > 0) \
+ if ((sigs)[signum]) \
+ (flags)[signum] = 0; \
+ } while (0)
+
+
+/* Command list pointer for the "stop" placeholder. */
+
+static struct cmd_list_element *stop_command;
+
+/* Nonzero if breakpoints are now inserted in the inferior. */
+
+static int breakpoints_inserted;
+
+/* Function inferior was in as of last step command. */
+
+static struct symbol *step_start_function;
+
+/* 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 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 */
+
+
+/* Things to clean up if we QUIT out of resume (). */
+/* ARGSUSED */
+static void
+resume_cleanups (arg)
+ int arg;
+{
+ normal_stop ();
+}
+
+/* Resume the inferior, but allow a QUIT. This is useful if the user
+ wants to interrupt some lengthy single-stepping operation
+ (for child processes, the SIGINT goes to the inferior, and so
+ we get a SIGINT random_signal, but for remote debugging and perhaps
+ other targets, that's not true).
+
+ STEP nonzero if we should step (zero to continue instead).
+ SIG is the signal to give the inferior (zero for none). */
+void
+resume (step, sig)
+ int step;
+ int sig;
+{
+ struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
+ QUIT;
+
+#ifdef CANNOT_STEP_BREAKPOINT
+ /* Most targets can step a breakpoint instruction, thus executing it
+ normally. But if this one cannot, just continue and we will hit
+ it anyway. */
+ if (step && breakpoints_inserted && breakpoint_here_p (read_pc ()))
+ step = 0;
+#endif
+
+#ifdef NO_SINGLE_STEP
+ if (step) {
+ single_step(sig); /* Do it the hard way, w/temp breakpoints */
+ step = 0; /* ...and don't ask hardware to do it. */
+ }
+#endif
+
+ /* Handle any optimized stores to the inferior NOW... */
+#ifdef DO_DEFERRED_STORES
+ DO_DEFERRED_STORES;
+#endif
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ target_resume (-1, step, sig);
+ discard_cleanups (old_cleanups);
+}
+
+
+/* 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;
+ 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 == (CORE_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 (breakpoint_here_p (read_pc ()))
+ oneproc = 1;
+ }
+ else
+ write_pc (addr);
+
+ 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;
+ }
+
+ 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;
+
+ /* Resume inferior. */
+ 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 ();
+}
+
+/* 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 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;
+ wait_for_inferior ();
+ normal_stop ();
+}
+
+/* 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;
+ breakpoint_init_inferior ();
+ stop_signal = 0; /* Don't confuse first call to proceed(). */
+}
+
+static void
+delete_breakpoint_current_contents (arg)
+ PTR arg;
+{
+ struct breakpoint **breakpointp = (struct breakpoint **)arg;
+ if (*breakpointp != NULL)
+ delete_breakpoint (*breakpointp);
+}
+
+/* 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 ()
+{
+ struct cleanup *old_cleanups;
+ WAITTYPE w;
+ int another_trap;
+ int random_signal;
+ CORE_ADDR stop_sp = 0;
+ CORE_ADDR stop_func_start;
+ char *stop_func_name;
+ CORE_ADDR prologue_pc = 0, tmp;
+ struct symtab_and_line sal;
+ int remove_breakpoints_on_following_step = 0;
+ int current_line;
+ int handling_longjmp = 0; /* FIXME */
+ struct breakpoint *step_resume_breakpoint = NULL;
+ int pid;
+
+ old_cleanups = make_cleanup (delete_breakpoint_current_contents,
+ &step_resume_breakpoint);
+ sal = find_pc_line(prev_pc, 0);
+ current_line = sal.line;
+
+ /* Are we stepping? */
+#define CURRENTLY_STEPPING() ((step_resume_breakpoint == NULL \
+ && !handling_longjmp \
+ && (step_range_end \
+ || trap_expected)) \
+ || bpstat_should_step ())
+
+ while (1)
+ {
+ /* Clean up saved state that will become invalid. */
+ flush_cached_frames ();
+ registers_changed ();
+
+ pid = target_wait (-1, &w);
+
+#ifdef SIGTRAP_STOP_AFTER_LOAD
+
+ /* Somebody called load(2), and it gave us a "trap signal after load".
+ Ignore it gracefully. */
+
+ SIGTRAP_STOP_AFTER_LOAD (w);
+#endif
+
+ /* 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_filtered ("\nProgram exited with code 0%o.\n",
+ (unsigned int)WEXITSTATUS (w));
+ else
+ if (!batch_mode())
+ printf_filtered ("\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))
+ {
+ char *signame;
+
+ stop_print_frame = 0;
+ stop_signal = WTERMSIG (w);
+ target_terminal_ours (); /* Must do this before mourn anyway */
+ target_kill (); /* kill mourns as well */
+#ifdef PRINT_RANDOM_SIGNAL
+ printf_filtered ("\nProgram terminated: ");
+ PRINT_RANDOM_SIGNAL (stop_signal);
+#else
+ printf_filtered ("\nProgram terminated with signal ");
+ signame = strsigno (stop_signal);
+ if (signame == NULL)
+ printf_filtered ("%d", stop_signal);
+ else
+ /* Do we need to print the number in addition to the name? */
+ printf_filtered ("%s (%d)", signame, stop_signal);
+ printf_filtered (", %s\n", safe_strsignal (stop_signal));
+#endif
+ printf_filtered ("The program no longer exists.\n");
+ fflush (stdout);
+#ifdef NO_SINGLE_STEP
+ one_stepped = 0;
+#endif
+ break;
+ }
+
+ stop_signal = WSTOPSIG (w);
+
+ if (pid != inferior_pid)
+ {
+ int save_pid = inferior_pid;
+
+ inferior_pid = pid; /* Setup for target memory/regs */
+ registers_changed ();
+ stop_pc = read_pc ();
+ inferior_pid = save_pid;
+ registers_changed ();
+ }
+ else
+ stop_pc = read_pc ();
+
+ if (stop_signal == SIGTRAP
+ && breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
+ if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK, pid))
+ {
+ /* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */
+ if (breakpoints_inserted)
+ {
+ remove_breakpoints ();
+ target_resume (pid, 1, 0); /* Single step */
+ /* FIXME: What if a signal arrives instead of the single-step
+ happening? */
+ target_wait (pid, NULL);
+ insert_breakpoints ();
+ }
+ target_resume (-1, 0, 0);
+ continue;
+ }
+ else
+ if (pid != inferior_pid)
+ goto switch_thread;
+
+ if (pid != inferior_pid)
+ {
+ int printed = 0;
+
+ if (!in_thread_list (pid))
+ {
+ fprintf (stderr, "[New %s]\n", target_pid_to_str (pid));
+ add_thread (pid);
+
+ target_resume (-1, 0, 0);
+ continue;
+ }
+ else
+ {
+ if (stop_signal >= NSIG || signal_print[stop_signal])
+ {
+ char *signame;
+
+ printed = 1;
+ target_terminal_ours_for_output ();
+ printf_filtered ("\nProgram received signal ");
+ signame = strsigno (stop_signal);
+ if (signame == NULL)
+ printf_filtered ("%d", stop_signal);
+ else
+ printf_filtered ("%s (%d)", signame, stop_signal);
+ printf_filtered (", %s\n", safe_strsignal (stop_signal));
+
+ fflush (stdout);
+ }
+
+ if (stop_signal == SIGTRAP
+ || stop_signal >= NSIG
+ || signal_stop[stop_signal])
+ {
+switch_thread:
+ inferior_pid = pid;
+ printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
+
+ flush_cached_frames ();
+ registers_changed ();
+ trap_expected = 0;
+ if (step_resume_breakpoint)
+ {
+ delete_breakpoint (step_resume_breakpoint);
+ step_resume_breakpoint = NULL;
+ }
+ prev_pc = 0;
+ prev_sp = 0;
+ prev_func_name = NULL;
+ step_range_start = 0;
+ step_range_end = 0;
+ step_frame_address = 0;
+ handling_longjmp = 0;
+ another_trap = 0;
+ }
+ else
+ {
+ if (printed)
+ target_terminal_inferior ();
+
+ /* Clear the signal if it should not be passed. */
+ if (signal_program[stop_signal] == 0)
+ stop_signal = 0;
+
+ target_resume (-1, 0, stop_signal);
+ continue;
+ }
+ }
+ }
+
+same_pid:
+
+#ifdef NO_SINGLE_STEP
+ if (one_stepped)
+ single_step (0); /* This actually cleans up the ss */
+#endif /* NO_SINGLE_STEP */
+
+/* If PC is pointing at a nullified instruction, then step beyond it so that
+ the user won't be confused when GDB appears to be ready to execute it. */
+
+ if (INSTRUCTION_NULLIFIED)
+ {
+ resume (1, 0);
+ continue;
+ }
+
+ set_current_frame ( create_new_frame (read_fp (), stop_pc));
+
+ stop_frame_address = FRAME_FP (get_current_frame ());
+ stop_sp = read_sp ();
+ 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. */
+ find_pc_partial_function (stop_pc, &stop_func_name, &stop_func_start,
+ NULL);
+ stop_func_start += FUNCTION_START_OFFSET;
+ another_trap = 0;
+ bpstat_clear (&stop_bpstat);
+ stop_step = 0;
+ stop_stack_dummy = 0;
+ stop_print_frame = 1;
+ 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. */
+
+ /* 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
+#ifdef SIGEMT
+ || stop_signal == SIGEMT
+#endif
+ ))
+ || 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_breakpoint
+ will be set and we should check whether we've hit the
+ step breakpoint. */
+ if (stop_signal == SIGTRAP && trap_expected
+ && step_resume_breakpoint == NULL)
+ bpstat_clear (&stop_bpstat);
+ else
+ {
+ /* See if there is a breakpoint at the current PC. */
+ stop_bpstat = bpstat_stop_status
+ (&stop_pc, stop_frame_address,
+#if DECR_PC_AFTER_BREAK
+ /* Notice the case of stepping through a jump
+ that lands 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. */
+ (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+ && CURRENTLY_STEPPING ())
+#else /* DECR_PC_AFTER_BREAK zero */
+ 0
+#endif /* DECR_PC_AFTER_BREAK zero */
+ );
+ /* 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
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+ || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
+ || (step_range_end && step_resume_breakpoint == NULL));
+ else
+ {
+ random_signal
+ = !(bpstat_explains_signal (stop_bpstat)
+ /* End of a stack dummy. Some systems (e.g. Sony
+ news) give another signal besides SIGTRAP,
+ so check here as well as above. */
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+ || PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
+ );
+ 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])
+ {
+ char *signame;
+ printed = 1;
+ target_terminal_ours_for_output ();
+#ifdef PRINT_RANDOM_SIGNAL
+ PRINT_RANDOM_SIGNAL (stop_signal);
+#else
+ printf_filtered ("\nProgram received signal ");
+ signame = strsigno (stop_signal);
+ if (signame == NULL)
+ printf_filtered ("%d", stop_signal);
+ else
+ /* Do we need to print the number as well as the name? */
+ printf_filtered ("%s (%d)", signame, stop_signal);
+ printf_filtered (", %s\n", safe_strsignal (stop_signal));
+#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 ();
+
+ /* Clear the signal if it should not be passed. */
+ if (signal_program[stop_signal] == 0)
+ stop_signal = 0;
+
+ /* I'm not sure whether this needs to be check_sigtramp2 or
+ whether it could/should be keep_going. */
+ goto check_sigtramp2;
+ }
+
+ /* Handle cases caused by hitting a breakpoint. */
+ {
+ CORE_ADDR jmp_buf_pc;
+ struct bpstat_what what;
+
+ what = bpstat_what (stop_bpstat);
+
+ if (what.call_dummy)
+ {
+ stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+ trap_expected_after_continue = 1;
+#endif
+ }
+
+ switch (what.main_action)
+ {
+ case BPSTAT_WHAT_SET_LONGJMP_RESUME:
+ /* If we hit the breakpoint at longjmp, disable it for the
+ duration of this command. Then, install a temporary
+ breakpoint at the target of the jmp_buf. */
+ disable_longjmp_breakpoint();
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ if (!GET_LONGJMP_TARGET(&jmp_buf_pc)) goto keep_going;
+
+ /* Need to blow away step-resume breakpoint, as it
+ interferes with us */
+ if (step_resume_breakpoint != NULL)
+ {
+ delete_breakpoint (step_resume_breakpoint);
+ step_resume_breakpoint = NULL;
+ what.step_resume = 0;
+ }
+
+#if 0
+ /* FIXME - Need to implement nested temporary breakpoints */
+ if (step_over_calls > 0)
+ set_longjmp_resume_breakpoint(jmp_buf_pc,
+ get_current_frame());
+ else
+#endif /* 0 */
+ set_longjmp_resume_breakpoint(jmp_buf_pc, NULL);
+ handling_longjmp = 1; /* FIXME */
+ goto keep_going;
+
+ case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
+ case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE:
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+#if 0
+ /* FIXME - Need to implement nested temporary breakpoints */
+ if (step_over_calls
+ && (stop_frame_address
+ INNER_THAN step_frame_address))
+ {
+ another_trap = 1;
+ goto keep_going;
+ }
+#endif /* 0 */
+ disable_longjmp_breakpoint();
+ handling_longjmp = 0; /* FIXME */
+ if (what.main_action == BPSTAT_WHAT_CLEAR_LONGJMP_RESUME)
+ break;
+ /* else fallthrough */
+
+ case BPSTAT_WHAT_SINGLE:
+ if (breakpoints_inserted)
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ another_trap = 1;
+ /* Still need to check other stuff, at least the case
+ where we are stepping and step out of the right range. */
+ break;
+
+ case BPSTAT_WHAT_STOP_NOISY:
+ stop_print_frame = 1;
+ /* We are about to nuke the step_resume_breakpoint via the
+ cleanup chain, so no need to worry about it here. */
+ goto stop_stepping;
+
+ case BPSTAT_WHAT_STOP_SILENT:
+ stop_print_frame = 0;
+ /* We are about to nuke the step_resume_breakpoint via the
+ cleanup chain, so no need to worry about it here. */
+ goto stop_stepping;
+
+ case BPSTAT_WHAT_KEEP_CHECKING:
+ break;
+ }
+
+ if (what.step_resume)
+ {
+ delete_breakpoint (step_resume_breakpoint);
+ step_resume_breakpoint = NULL;
+
+ /* If were waiting for a trap, hitting the step_resume_break
+ doesn't count as getting it. */
+ if (trap_expected)
+ 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. */
+
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+ /* This is the old way of detecting the end of the stack dummy.
+ An architecture which defines CALL_DUMMY_BREAKPOINT_OFFSET gets
+ handled above. As soon as we can test it on all of them, all
+ architectures should define it. */
+
+ /* If this is the breakpoint at the end of a stack dummy,
+ just stop silently, unless the user was doing an si/ni, in which
+ case she'd better know what she's doing. */
+
+ if (PC_IN_CALL_DUMMY (stop_pc, stop_sp, stop_frame_address)
+ && !step_range_end)
+ {
+ stop_print_frame = 0;
+ stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+ trap_expected_after_continue = 1;
+#endif
+ break;
+ }
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
+
+ if (step_resume_breakpoint)
+ /* Having a step-resume breakpoint overrides anything
+ else having to do with stepping commands until
+ that breakpoint is reached. */
+ /* I suspect this could/should be keep_going, because if the
+ check_sigtramp2 check succeeds, then it will put in another
+ step_resume_breakpoint, and we aren't (yet) prepared to nest
+ them. */
+ goto check_sigtramp2;
+
+ if (step_range_end == 0)
+ /* Likewise if we aren't even stepping. */
+ /* I'm not sure whether this needs to be check_sigtramp2 or
+ whether it could/should be keep_going. */
+ goto check_sigtramp2;
+
+ /* If stepping through a line, keep going if still within it. */
+ if (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)))
+ {
+ /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
+ So definately need to check for sigtramp here. */
+ goto check_sigtramp2;
+ }
+
+ /* We stepped out of the stepping range. See if that was due
+ to a subroutine call that we should proceed to the end of. */
+
+ /* 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. */
+ {
+ struct symtab_and_line sr_sal;
+
+ sr_sal.pc = prev_pc;
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, get_current_frame (),
+ bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+ }
+
+ /* If this is stepi or nexti, make sure that the stepping range
+ gets us past that instruction. */
+ if (step_range_end == 1)
+ /* FIXME: Does this run afoul of the code below which, if
+ we step into the middle of a line, resets the stepping
+ range? */
+ step_range_end = (step_range_start = prev_pc) + 1;
+
+ remove_breakpoints_on_following_step = 1;
+ goto keep_going;
+ }
+
+ if (stop_func_start)
+ {
+ /* Do this after the IN_SIGTRAMP check; it might give
+ an error. */
+ prologue_pc = stop_func_start;
+ SKIP_PROLOGUE (prologue_pc);
+ }
+
+ if ((/* Might be a non-recursive call. If the symbols are missing
+ enough that stop_func_start == prev_func_start even though
+ they are really two functions, we will treat some calls as
+ jumps. */
+ stop_func_start != prev_func_start
+
+ /* Might be a recursive call if either we have a prologue
+ or the call instruction itself saves the PC on the stack. */
+ || prologue_pc != stop_func_start
+ || stop_sp != prev_sp)
+ && (/* PC is completely out of bounds of any known objfiles. Treat
+ like a subroutine call. */
+ !stop_func_start
+
+ /* If we do a call, we will be at the start of a function. */
+ || stop_pc == stop_func_start
+
+#if 0
+ /* Not conservative enough for 4.11. FIXME: enable this
+ after 4.11. */
+ /* Except on the Alpha with -O (and perhaps other machines
+ with similar calling conventions), in which we might
+ call the address after the load of gp. Since prologues
+ don't contain calls, we can't return to within one, and
+ we don't jump back into them, so this check is OK. */
+ || stop_pc < prologue_pc
+#endif
+
+ /* If we end up in certain places, it means we did a subroutine
+ call. I'm not completely sure this is necessary now that we
+ have the above checks with stop_func_start (and now that
+ find_pc_partial_function is pickier). */
+ || IN_SOLIB_TRAMPOLINE (stop_pc, stop_func_name)
+
+ /* If none of the above apply, it is a jump within a function,
+ or a return from a subroutine. The other case is longjmp,
+ which can no longer happen here as long as the
+ handling_longjmp stuff is working. */
+ ))
+ {
+ /* It's a subroutine call. */
+
+ if (step_over_calls == 0)
+ {
+ /* I presume that step_over_calls is only 0 when we're
+ supposed to be stepping at the assembly language level
+ ("stepi"). Just stop. */
+ stop_step = 1;
+ break;
+ }
+
+ if (step_over_calls > 0)
+ /* We're doing a "next". */
+ goto step_over_function;
+
+ /* If we are in a function call trampoline (a stub between
+ the calling routine and the real function), locate the real
+ function. That's what tells us (a) whether we want to step
+ into it at all, and (b) what prologue we want to run to
+ the end of, if we do step into it. */
+ tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
+ if (tmp != 0)
+ stop_func_start = tmp;
+
+ /* If we have line number information for the function we
+ are thinking of stepping into, step into it.
+
+ If there are several symtabs at that PC (e.g. with include
+ files), just want to know whether *any* of them have line
+ numbers. find_pc_line handles this. */
+ {
+ struct symtab_and_line tmp_sal;
+
+ tmp_sal = find_pc_line (stop_func_start, 0);
+ if (tmp_sal.line != 0)
+ goto step_into_function;
+ }
+
+step_over_function:
+ /* A subroutine call has happened. */
+ {
+ /* Set a special breakpoint after the return */
+ struct symtab_and_line sr_sal;
+ sr_sal.pc =
+ ADDR_BITS_REMOVE
+ (SAVED_PC_AFTER_CALL (get_current_frame ()));
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, get_current_frame (),
+ bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+ }
+ goto keep_going;
+
+step_into_function:
+ /* Subroutine call with source code we should not step over.
+ Do step to the first line of code in it. */
+ 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. */
+ {
+ struct symtab_and_line sr_sal;
+
+ sr_sal.pc = stop_func_start;
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ /* 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_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+
+ /* And make sure stepping stops right away then. */
+ step_range_end = step_range_start;
+ }
+ goto keep_going;
+ }
+
+ /* We've wandered out of the step range (but haven't done a
+ subroutine call or return). (Is that true? I think we get
+ here if we did a return and maybe a longjmp). */
+
+ sal = find_pc_line(stop_pc, 0);
+
+ if (step_range_end == 1)
+ {
+ /* It is stepi or nexti. We always want to stop stepping after
+ one instruction. */
+ stop_step = 1;
+ break;
+ }
+
+ if (sal.line == 0)
+ {
+ /* We have no line number information. That means to stop
+ stepping (does this always happen right after one instruction,
+ when we do "s" in a function with no line numbers,
+ or can this happen as a result of a return or longjmp?). */
+ stop_step = 1;
+ break;
+ }
+
+ if (stop_pc == sal.pc && current_line != sal.line)
+ {
+ /* We are at the start of a different line. So stop. Note that
+ we don't stop if we step into the middle of a different line.
+ That is said to make things like for (;;) statements work
+ better. */
+ stop_step = 1;
+ break;
+ }
+
+ /* We aren't done stepping.
+
+ Optimize by setting the stepping range to the line.
+ (We might not be in the original line, but if we entered a
+ new line in mid-statement, we continue stepping. This makes
+ things like for(;;) statements work better.) */
+ step_range_start = sal.pc;
+ step_range_end = sal.end;
+ goto keep_going;
+
+ check_sigtramp2:
+ 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. FIXME: This should
+ be more enduring than a step_resume breakpoint; we should know
+ that we will later need to keep going rather than re-hitting
+ the breakpoint here (see testsuite/gdb.t06/signals.exp where
+ it says "exceedingly difficult"). */
+ struct symtab_and_line sr_sal;
+
+ sr_sal.pc = prev_pc;
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, get_current_frame (),
+ bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+
+ remove_breakpoints_on_following_step = 1;
+ another_trap = 1;
+ }
+
+ keep_going:
+ /* Come to this label when you need to resume the inferior.
+ It's really much cleaner to do a goto than a maze of if-else
+ conditions. */
+
+ /* 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. */
+ resume (CURRENTLY_STEPPING (), 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_breakpoint == NULL &&
+ remove_breakpoints_on_following_step)
+ {
+ remove_breakpoints_on_following_step = 0;
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ }
+ else if (!breakpoints_inserted &&
+ (step_resume_breakpoint != NULL || !another_trap))
+ {
+ 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. */
+ /* FIXME: Shouldn't this be based on the valid bit of the SXIP?
+ (this is only used on the 88k). */
+
+ if (!bpstat_explains_signal (stop_bpstat)
+ && (stop_signal != SIGCLD)
+ && !stopped_by_random_signal)
+ SHIFT_INST_REGS();
+#endif /* SHIFT_INST_REGS */
+
+ resume (CURRENTLY_STEPPING (), stop_signal);
+ }
+ }
+
+ stop_stepping:
+ 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;
+ }
+ do_cleanups (old_cleanups);
+}
+
+/* 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())
+ (get_current_frame ())->pc = read_pc ();
+
+ if (breakpoints_failed)
+ {
+ target_terminal_ours_for_output ();
+ print_sys_errmsg ("ptrace", breakpoints_failed);
+ printf_filtered ("Stopped; cannot insert breakpoints.\n\
+The same program may be running in another process.\n");
+ }
+
+ if (target_has_execution && breakpoints_inserted)
+ if (remove_breakpoints ())
+ {
+ target_terminal_ours_for_output ();
+ printf_filtered ("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 ();
+
+ /* Look up the hook_stop and run it if it exists. */
+
+ if (stop_command->hook)
+ {
+ catch_errors (hook_stop_stub, (char *)stop_command->hook,
+ "Error while running hook_stop:\n", RETURN_MASK_ALL);
+ }
+
+ if (!target_has_stack)
+ return;
+
+ /* Select innermost stack frame except on return from a stack dummy routine,
+ or if the program has exited. Print it without a level number if
+ we have changed functions or hit a breakpoint. Print source line
+ if we have one. */
+ if (!stop_stack_dummy)
+ {
+ select_frame (get_current_frame (), 0);
+
+ if (stop_print_frame)
+ {
+ int source_only;
+
+ source_only = bpstat_print (stop_bpstat);
+ source_only = source_only ||
+ ( stop_step
+ && step_frame_address == stop_frame_address
+ && step_start_function == find_pc_function (stop_pc));
+
+ print_stack_frame (selected_frame, -1, source_only? -1: 1);
+
+ /* 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);
+ }
+}
+
+static int
+hook_stop_stub (cmd)
+ char *cmd;
+{
+ execute_user_command ((struct cmd_list_element *)cmd, 0);
+ return (0);
+}
+
+int signal_stop_state (signo)
+ int signo;
+{
+ return ((signo >= 0 && signo < NSIG) ? signal_stop[signo] : 0);
+}
+
+int signal_print_state (signo)
+ int signo;
+{
+ return ((signo >= 0 && signo < NSIG) ? signal_print[signo] : 0);
+}
+
+int signal_pass_state (signo)
+ int signo;
+{
+ return ((signo >= 0 && signo < NSIG) ? signal_program[signo] : 0);
+}
+
+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 *name;
+
+ if ((name = strsigno (number)) == NULL)
+ printf_filtered ("%d\t\t", number);
+ else
+ printf_filtered ("%s (%d)\t", name, 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", safe_strsignal (number));
+}
+
+/* Specify how various signals in the inferior should be handled. */
+
+static void
+handle_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ int digits, wordlen;
+ int sigfirst, signum, siglast;
+ int allsigs;
+ int nsigs;
+ unsigned char *sigs;
+ struct cleanup *old_chain;
+
+ if (args == NULL)
+ {
+ error_no_arg ("signal to handle");
+ }
+
+ /* Allocate and zero an array of flags for which signals to handle. */
+
+ nsigs = signo_max () + 1;
+ sigs = (unsigned char *) alloca (nsigs);
+ memset (sigs, 0, nsigs);
+
+ /* Break the command line up into args. */
+
+ argv = buildargv (args);
+ if (argv == NULL)
+ {
+ nomem (0);
+ }
+ old_chain = make_cleanup (freeargv, (char *) argv);
+
+ /* Walk through the args, looking for signal numbers, signal names, and
+ actions. Signal numbers and signal names may be interspersed with
+ actions, with the actions being performed for all signals cumulatively
+ specified. Signal ranges can be specified as <LOW>-<HIGH>. */
+
+ while (*argv != NULL)
+ {
+ wordlen = strlen (*argv);
+ for (digits = 0; isdigit ((*argv)[digits]); digits++) {;}
+ allsigs = 0;
+ sigfirst = siglast = -1;
+
+ if (wordlen >= 1 && !strncmp (*argv, "all", wordlen))
+ {
+ /* Apply action to all signals except those used by the
+ debugger. Silently skip those. */
+ allsigs = 1;
+ sigfirst = 0;
+ siglast = nsigs - 1;
+ }
+ else if (wordlen >= 1 && !strncmp (*argv, "stop", wordlen))
+ {
+ SET_SIGS (nsigs, sigs, signal_stop);
+ SET_SIGS (nsigs, sigs, signal_print);
+ }
+ else if (wordlen >= 1 && !strncmp (*argv, "ignore", wordlen))
+ {
+ UNSET_SIGS (nsigs, sigs, signal_program);
+ }
+ else if (wordlen >= 2 && !strncmp (*argv, "print", wordlen))
+ {
+ SET_SIGS (nsigs, sigs, signal_print);
+ }
+ else if (wordlen >= 2 && !strncmp (*argv, "pass", wordlen))
+ {
+ SET_SIGS (nsigs, sigs, signal_program);
+ }
+ else if (wordlen >= 3 && !strncmp (*argv, "nostop", wordlen))
+ {
+ UNSET_SIGS (nsigs, sigs, signal_stop);
+ }
+ else if (wordlen >= 3 && !strncmp (*argv, "noignore", wordlen))
+ {
+ SET_SIGS (nsigs, sigs, signal_program);
+ }
+ else if (wordlen >= 4 && !strncmp (*argv, "noprint", wordlen))
+ {
+ UNSET_SIGS (nsigs, sigs, signal_print);
+ UNSET_SIGS (nsigs, sigs, signal_stop);
+ }
+ else if (wordlen >= 4 && !strncmp (*argv, "nopass", wordlen))
+ {
+ UNSET_SIGS (nsigs, sigs, signal_program);
+ }
+ else if (digits > 0)
+ {
+ sigfirst = siglast = atoi (*argv);
+ if ((*argv)[digits] == '-')
+ {
+ siglast = atoi ((*argv) + digits + 1);
+ }
+ if (sigfirst > siglast)
+ {
+ /* Bet he didn't figure we'd think of this case... */
+ signum = sigfirst;
+ sigfirst = siglast;
+ siglast = signum;
+ }
+ if (sigfirst < 0 || sigfirst >= nsigs)
+ {
+ error ("Signal %d not in range 0-%d", sigfirst, nsigs - 1);
+ }
+ if (siglast < 0 || siglast >= nsigs)
+ {
+ error ("Signal %d not in range 0-%d", siglast, nsigs - 1);
+ }
+ }
+ else if ((signum = strtosigno (*argv)) != 0)
+ {
+ sigfirst = siglast = signum;
+ }
+ else
+ {
+ /* Not a number and not a recognized flag word => complain. */
+ error ("Unrecognized or ambiguous flag word: \"%s\".", *argv);
+ }
+
+ /* If any signal numbers or symbol names were found, set flags for
+ which signals to apply actions to. */
+
+ for (signum = sigfirst; signum >= 0 && signum <= siglast; signum++)
+ {
+ switch (signum)
+ {
+ case SIGTRAP:
+ case SIGINT:
+ if (!allsigs && !sigs[signum])
+ {
+ if (query ("%s is used by the debugger.\nAre you sure you want to change it? ", strsigno (signum)))
+ {
+ sigs[signum] = 1;
+ }
+ else
+ {
+ printf ("Not confirmed, unchanged.\n");
+ fflush (stdout);
+ }
+ }
+ break;
+ default:
+ sigs[signum] = 1;
+ break;
+ }
+ }
+
+ argv++;
+ }
+
+ target_notice_signals(inferior_pid);
+
+ if (from_tty)
+ {
+ /* Show the results. */
+ sig_print_header ();
+ for (signum = 0; signum < nsigs; signum++)
+ {
+ if (sigs[signum])
+ {
+ sig_print_info (signum);
+ }
+ }
+ }
+
+ do_cleanups (old_chain);
+}
+
+/* Print current contents of the tables set by the handle command. */
+
+static void
+signals_info (signum_exp, from_tty)
+ char *signum_exp;
+ int from_tty;
+{
+ register int i;
+ sig_print_header ();
+
+ if (signum_exp)
+ {
+ /* First see if this is a symbol name. */
+ i = strtosigno (signum_exp);
+ if (i == 0)
+ {
+ /* 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");
+}
+
+/* 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->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->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;
+
+ memcpy (inf_status->stop_registers, stop_registers, REGISTER_BYTES);
+
+ read_register_bytes (0, inf_status->registers, REGISTER_BYTES);
+
+ record_selected_frame (&(inf_status->selected_frame_address),
+ &(inf_status->selected_level));
+ return;
+}
+
+struct restore_selected_frame_args {
+ FRAME_ADDR frame_address;
+ int level;
+};
+
+static int restore_selected_frame PARAMS ((char *));
+
+/* Restore the selected frame. args is really a struct
+ restore_selected_frame_args * (declared as char * for catch_errors)
+ telling us what frame to restore. Returns 1 for success, or 0 for
+ failure. An error message will have been printed on error. */
+static int
+restore_selected_frame (args)
+ char *args;
+{
+ struct restore_selected_frame_args *fr =
+ (struct restore_selected_frame_args *) args;
+ FRAME fid;
+ int level = fr->level;
+
+ fid = find_relative_frame (get_current_frame (), &level);
+
+ /* If inf_status->selected_frame_address is NULL, there was no
+ previously selected frame. */
+ if (fid == 0 ||
+ FRAME_FP (fid) != fr->frame_address ||
+ level != 0)
+ {
+ warning ("Unable to restore previously selected frame.\n");
+ return 0;
+ }
+ select_frame (fid, fr->level);
+ return(1);
+}
+
+void
+restore_inferior_status (inf_status)
+ struct inferior_status *inf_status;
+{
+ 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;
+ 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;
+
+ memcpy (stop_registers, inf_status->stop_registers, REGISTER_BYTES);
+
+ /* The inferior can be gone if the user types "print exit(0)"
+ (and perhaps other times). */
+ if (target_has_execution)
+ write_register_bytes (0, inf_status->registers, REGISTER_BYTES);
+
+ /* The inferior can be gone if the user types "print exit(0)"
+ (and perhaps other times). */
+
+ /* FIXME: If we are being called after stopping in a function which
+ is called from gdb, we should not be trying to restore the
+ selected frame; it just prints a spurious error message (The
+ message is useful, however, in detecting bugs in gdb (like if gdb
+ clobbers the stack)). In fact, should we be restoring the
+ inferior status at all in that case? . */
+
+ if (target_has_stack && inf_status->restore_stack_info)
+ {
+ struct restore_selected_frame_args fr;
+ fr.level = inf_status->selected_level;
+ fr.frame_address = inf_status->selected_frame_address;
+ /* The point of catch_errors is that if the stack is clobbered,
+ walking the stack might encounter a garbage pointer and error()
+ trying to dereference it. */
+ if (catch_errors (restore_selected_frame, &fr,
+ "Unable to restore previously selected frame:\n",
+ RETURN_MASK_ERROR) == 0)
+ /* Error in restoring the selected frame. Select the innermost
+ frame. */
+ select_frame (get_current_frame (), 0);
+ }
+}
+
+
+void
+_initialize_infrun ()
+{
+ register int i;
+ register int numsigs;
+
+ 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_info_alias ("handle", "signals", 0);
+
+ add_com ("handle", class_run, handle_command,
+ "Specify how to handle a signal.\n\
+Args are signal numbers and actions to apply to those signals.\n\
+Signal numbers may be numeric (ex. 11) or symbolic (ex. SIGSEGV).\n\
+Numeric ranges may be specified with the form LOW-HIGH (ex. 14-21).\n\
+The special arg \"all\" is recognized to mean all signals except those\n\
+used by the debugger, typically SIGTRAP and SIGINT.\n\
+Recognized actions include \"stop\", \"nostop\", \"print\", \"noprint\",\n\
+\"pass\", \"nopass\", \"ignore\", or \"noignore\".\n\
+Stop means reenter debugger if this signal happens (implies print).\n\
+Print means print a message if this signal happens.\n\
+Pass means let program see this signal; otherwise program doesn't know.\n\
+Ignore is a synonym for nopass and noignore is a synonym for pass.\n\
+Pass and Stop may be combined.");
+
+ stop_command = add_cmd ("stop", class_obscure, not_just_help_class_command,
+ "There is no `stop' command, but you can set a hook on `stop'.\n\
+This allows you to set a list of commands to be run each time execution\n\
+of the program stops.", &cmdlist);
+
+ numsigs = signo_max () + 1;
+ signal_stop = (unsigned char *)
+ xmalloc (sizeof (signal_stop[0]) * numsigs);
+ signal_print = (unsigned char *)
+ xmalloc (sizeof (signal_print[0]) * numsigs);
+ signal_program = (unsigned char *)
+ xmalloc (sizeof (signal_program[0]) * numsigs);
+ for (i = 0; i < numsigs; 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/gnu/usr.bin/gdb/gdb/inftarg.c b/gnu/usr.bin/gdb/gdb/inftarg.c
new file mode 100644
index 000000000000..f937be4ea6e1
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/inftarg.c
@@ -0,0 +1,310 @@
+/* Target-vector operations for controlling Unix child processes, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+
+#include <signal.h>
+
+static void
+child_prepare_to_store PARAMS ((void));
+
+#ifndef CHILD_WAIT
+static int
+child_wait PARAMS ((int, int *));
+#endif /* CHILD_WAIT */
+
+static void
+child_open PARAMS ((char *, int));
+
+static void
+child_files_info PARAMS ((struct target_ops *));
+
+static void
+child_detach PARAMS ((char *, int));
+
+static void
+child_attach PARAMS ((char *, int));
+
+static void
+ptrace_me PARAMS ((void));
+
+static void
+ptrace_him PARAMS ((int));
+
+static void
+child_create_inferior PARAMS ((char *, char *, char **));
+
+static void
+child_mourn_inferior PARAMS ((void));
+
+static int
+child_can_run PARAMS ((void));
+
+extern char **environ;
+
+/* Forward declaration */
+extern struct target_ops child_ops;
+
+#ifndef CHILD_WAIT
+
+/* Wait for child to do something. Return pid of child, or -1 in case
+ of error; store status through argument pointer STATUS. */
+
+static int
+child_wait (pid, status)
+ int pid;
+ int *status;
+{
+ int save_errno;
+
+ do {
+ if (attach_flag)
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
+ pid = wait (status);
+ save_errno = errno;
+
+ if (attach_flag)
+ clear_sigint_trap();
+
+ if (pid == -1)
+ {
+ if (save_errno == EINTR)
+ continue;
+ fprintf (stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
+ *status = 42; /* Claim it exited with signal 42 */
+ return -1;
+ }
+ } while (pid != inferior_pid); /* Some other child died or stopped */
+ return pid;
+}
+#endif /* CHILD_WAIT */
+
+/* Attach to process PID, then initialize for debugging it. */
+
+static void
+child_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *exec_file;
+ int pid;
+
+ 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 (pid == getpid()) /* Trying to masturbate? */
+ error ("I refuse to debug myself!");
+
+ if (from_tty)
+ {
+ exec_file = (char *) get_exec_file (0);
+
+ if (exec_file)
+ printf ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
+ else
+ printf ("Attaching to %s\n", target_pid_to_str (pid));
+
+ fflush (stdout);
+ }
+
+ attach (pid);
+ inferior_pid = pid;
+ push_target (&child_ops);
+#endif /* ATTACH_DETACH */
+}
+
+
+/* Take a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We'd 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 from program: %s %s\n", exec_file,
+ target_pid_to_str (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. */
+
+static void
+child_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+child_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf ("\tUsing the running image of %s %s.\n",
+ attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
+}
+
+/* ARGSUSED */
+static void
+child_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
+/* Stub function which causes the inferior that runs it, to be ptrace-able
+ by its parent process. */
+
+static void
+ptrace_me ()
+{
+ /* "Trace me, Dr. Memory!" */
+ call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
+}
+
+/* Stub function which causes the GDB that runs it, to start ptrace-ing
+ the child process. */
+
+static void
+ptrace_him (pid)
+ int pid;
+{
+ push_target (&child_ops);
+}
+
+/* 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(). */
+
+static void
+child_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him);
+ /* We are at the first instruction we care about. */
+ /* Pedal to the metal... */
+ proceed ((CORE_ADDR) -1, 0, 0);
+}
+
+static void
+child_mourn_inferior ()
+{
+ unpush_target (&child_ops);
+ generic_mourn_inferior ();
+}
+
+static int
+child_can_run ()
+{
+ return(1);
+}
+
+struct target_ops child_ops = {
+ "child", /* to_shortname */
+ "Unix child process", /* to_longname */
+ "Unix child process (started by the \"run\" command).", /* to_doc */
+ child_open, /* to_open */
+ 0, /* to_close */
+ child_attach, /* to_attach */
+ child_detach, /* to_detach */
+ child_resume, /* to_resume */
+ child_wait, /* to_wait */
+ fetch_inferior_registers, /* to_fetch_registers */
+ store_inferior_registers, /* to_store_registers */
+ child_prepare_to_store, /* to_prepare_to_store */
+ child_xfer_memory, /* to_xfer_memory */
+ child_files_info, /* to_files_info */
+ memory_insert_breakpoint, /* to_insert_breakpoint */
+ memory_remove_breakpoint, /* to_remove_breakpoint */
+ terminal_init_inferior, /* to_terminal_init */
+ terminal_inferior, /* to_terminal_inferior */
+ terminal_ours_for_output, /* to_terminal_ours_for_output */
+ terminal_ours, /* to_terminal_ours */
+ child_terminal_info, /* to_terminal_info */
+ kill_inferior, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+ child_create_inferior, /* to_create_inferior */
+ child_mourn_inferior, /* to_mourn_inferior */
+ child_can_run, /* to_can_run */
+ 0, /* to_notice_signals */
+ process_stratum, /* to_stratum */
+ 0, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* sections */
+ 0, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_inftarg ()
+{
+ add_target (&child_ops);
+}
diff --git a/gnu/usr.bin/gdb/gdb/init.c b/gnu/usr.bin/gdb/gdb/init.c
new file mode 100644
index 000000000000..26afe1d761eb
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/init.c
@@ -0,0 +1,47 @@
+/* Do not modify this file. It is created automatically by "munch". */
+void initialize_all_files () {
+ {extern void _initialize_blockframe (); _initialize_blockframe ();}
+ {extern void _initialize_breakpoint (); _initialize_breakpoint ();}
+ {extern void _initialize_buildsym (); _initialize_buildsym ();}
+ {extern void _initialize_c_language (); _initialize_c_language ();}
+ {extern void _initialize_chill_language (); _initialize_chill_language ();}
+ {extern void _initialize_coffread (); _initialize_coffread ();}
+ {extern void _initialize_command (); _initialize_command ();}
+ {extern void _initialize_complaints (); _initialize_complaints ();}
+ {extern void _initialize_copying (); _initialize_copying ();}
+ {extern void _initialize_core (); _initialize_core ();}
+ {extern void _initialize_corelow (); _initialize_corelow ();}
+ {extern void _initialize_cp_valprint (); _initialize_cp_valprint ();}
+ {extern void _initialize_dbxread (); _initialize_dbxread ();}
+ {extern void _initialize_demangler (); _initialize_demangler ();}
+ {extern void _initialize_elfread (); _initialize_elfread ();}
+ {extern void _initialize_exec (); _initialize_exec ();}
+ {extern void _initialize_gdbtypes (); _initialize_gdbtypes ();}
+ {extern void _initialize_infcmd (); _initialize_infcmd ();}
+ {extern void _initialize_inflow (); _initialize_inflow ();}
+ {extern void _initialize_infrun (); _initialize_infrun ();}
+ {extern void _initialize_inftarg (); _initialize_inftarg ();}
+ {extern void _initialize_language (); _initialize_language ();}
+ {extern void _initialize_m2_language (); _initialize_m2_language ();}
+ {extern void _initialize_maint_cmds (); _initialize_maint_cmds ();}
+ {extern void _initialize_mipsread (); _initialize_mipsread ();}
+ {extern void _initialize_nlmread (); _initialize_nlmread ();}
+ {extern void _initialize_parse (); _initialize_parse ();}
+ {extern void _initialize_printcmd (); _initialize_printcmd ();}
+ {extern void _initialize_remote (); _initialize_remote ();}
+ {extern void _initialize_ser_hardwire (); _initialize_ser_hardwire ();}
+ {extern void _initialize_solib (); _initialize_solib ();}
+ {extern void _initialize_source (); _initialize_source ();}
+ {extern void _initialize_sr_support (); _initialize_sr_support ();}
+ {extern void _initialize_stabsread (); _initialize_stabsread ();}
+ {extern void _initialize_stack (); _initialize_stack ();}
+ {extern void _initialize_symfile (); _initialize_symfile ();}
+ {extern void _initialize_symmisc (); _initialize_symmisc ();}
+ {extern void _initialize_symtab (); _initialize_symtab ();}
+ {extern void _initialize_targets (); _initialize_targets ();}
+ {extern void _initialize_thread (); _initialize_thread ();}
+ {extern void _initialize_typeprint (); _initialize_typeprint ();}
+ {extern void _initialize_utils (); _initialize_utils ();}
+ {extern void _initialize_valprint (); _initialize_valprint ();}
+ {extern void _initialize_values (); _initialize_values ();}
+}
diff --git a/gnu/usr.bin/gdb/gdb/language.c b/gnu/usr.bin/gdb/gdb/language.c
new file mode 100644
index 000000000000..be519532caf3
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/language.c
@@ -0,0 +1,1332 @@
+/* Multiple source language support for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Contributed by the Department of Computer Science at the State University
+ of New York at Buffalo.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file contains functions that return things that are specific
+ to languages. Each function should examine current_language if necessary,
+ and return the appropriate result. */
+
+/* FIXME: Most of these would be better organized as macros which
+ return data out of a "language-specific" struct pointer that is set
+ whenever the working language changes. That would be a lot faster. */
+
+#include "defs.h"
+#include <string.h>
+#include <varargs.h>
+
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "frame.h"
+#include "expression.h"
+#include "language.h"
+#include "target.h"
+#include "parser-defs.h"
+
+static void
+show_language_command PARAMS ((char *, int));
+
+static void
+set_language_command PARAMS ((char *, int));
+
+static void
+show_type_command PARAMS ((char *, int));
+
+static void
+set_type_command PARAMS ((char *, int));
+
+static void
+show_range_command PARAMS ((char *, int));
+
+static void
+set_range_command PARAMS ((char *, int));
+
+static void
+set_range_str PARAMS ((void));
+
+static void
+set_type_str PARAMS ((void));
+
+static void
+set_lang_str PARAMS ((void));
+
+static void
+unk_lang_error PARAMS ((char *));
+
+static int
+unk_lang_parser PARAMS ((void));
+
+static void
+show_check PARAMS ((char *, int));
+
+static void
+set_check PARAMS ((char *, int));
+
+static void
+set_type_range PARAMS ((void));
+
+/* Forward declaration */
+extern const struct language_defn unknown_language_defn;
+extern char *warning_pre_print;
+
+/* The current (default at startup) state of type and range checking.
+ (If the modes are set to "auto", though, these are changed based
+ on the default language at startup, and then again based on the
+ language of the first source file. */
+
+enum range_mode range_mode = range_mode_auto;
+enum range_check range_check = range_check_off;
+enum type_mode type_mode = type_mode_auto;
+enum type_check type_check = type_check_off;
+
+/* The current language and language_mode (see language.h) */
+
+const struct language_defn *current_language = &unknown_language_defn;
+enum language_mode language_mode = language_mode_auto;
+
+/* The language that the user expects to be typing in (the language
+ of main(), or the last language we notified them about, or C). */
+
+const struct language_defn *expected_language;
+
+/* The list of supported languages. The list itself is malloc'd. */
+
+static const struct language_defn **languages;
+static unsigned languages_size;
+static unsigned languages_allocsize;
+#define DEFAULT_ALLOCSIZE 4
+
+/* The "set language/type/range" commands all put stuff in these
+ buffers. This is to make them work as set/show commands. The
+ user's string is copied here, then the set_* commands look at
+ them and update them to something that looks nice when it is
+ printed out. */
+
+static char *language;
+static char *type;
+static char *range;
+
+/* Warning issued when current_language and the language of the current
+ frame do not match. */
+char lang_frame_mismatch_warn[] =
+ "Warning: the current language does not match this frame.";
+
+
+/* This page contains the functions corresponding to GDB commands
+ and their helpers. */
+
+/* Show command. Display a warning if the language set
+ does not match the frame. */
+static void
+show_language_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ enum language flang; /* The language of the current frame */
+
+ flang = get_frame_language();
+ if (flang != language_unknown &&
+ language_mode == language_mode_manual &&
+ current_language->la_language != flang)
+ printf_filtered("%s\n",lang_frame_mismatch_warn);
+}
+
+/* Set command. Change the current working language. */
+static void
+set_language_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ int i;
+ enum language flang;
+ char *err_lang;
+
+ /* FIXME -- do this from the list, with HELP. */
+ if (!language || !language[0]) {
+ printf("The currently understood settings are:\n\n");
+ printf ("local or auto Automatic setting based on source file\n");
+ printf ("c Use the C language\n");
+ printf ("c++ Use the C++ language\n");
+ printf ("chill Use the Chill language\n");
+ printf ("modula-2 Use the Modula-2 language\n");
+ /* Restore the silly string. */
+ set_language(current_language->la_language);
+ return;
+ }
+
+ /* Search the list of languages for a match. */
+ for (i = 0; i < languages_size; i++) {
+ if (STREQ (languages[i]->la_name, language)) {
+ /* Found it! Go into manual mode, and use this language. */
+ if (languages[i]->la_language == language_auto) {
+ /* Enter auto mode. Set to the current frame's language, if known. */
+ language_mode = language_mode_auto;
+ flang = get_frame_language();
+ if (flang!=language_unknown)
+ set_language(flang);
+ expected_language = current_language;
+ return;
+ } else {
+ /* Enter manual mode. Set the specified language. */
+ language_mode = language_mode_manual;
+ current_language = languages[i];
+ set_type_range ();
+ set_lang_str();
+ expected_language = current_language;
+ return;
+ }
+ }
+ }
+
+ /* Reset the language (esp. the global string "language") to the
+ correct values. */
+ err_lang=savestring(language,strlen(language));
+ make_cleanup (free, err_lang); /* Free it after error */
+ set_language(current_language->la_language);
+ error ("Unknown language `%s'.",err_lang);
+}
+
+/* Show command. Display a warning if the type setting does
+ not match the current language. */
+static void
+show_type_command(ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (type_check != current_language->la_type_check)
+ printf(
+"Warning: the current type check setting does not match the language.\n");
+}
+
+/* Set command. Change the setting for type checking. */
+static void
+set_type_command(ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (STREQ(type,"on"))
+ {
+ type_check = type_check_on;
+ type_mode = type_mode_manual;
+ }
+ else if (STREQ(type,"warn"))
+ {
+ type_check = type_check_warn;
+ type_mode = type_mode_manual;
+ }
+ else if (STREQ(type,"off"))
+ {
+ type_check = type_check_off;
+ type_mode = type_mode_manual;
+ }
+ else if (STREQ(type,"auto"))
+ {
+ type_mode = type_mode_auto;
+ set_type_range();
+ /* Avoid hitting the set_type_str call below. We
+ did it in set_type_range. */
+ return;
+ }
+ set_type_str();
+ show_type_command((char *)NULL, from_tty);
+}
+
+/* Show command. Display a warning if the range setting does
+ not match the current language. */
+static void
+show_range_command(ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+
+ if (range_check != current_language->la_range_check)
+ printf(
+"Warning: the current range check setting does not match the language.\n");
+}
+
+/* Set command. Change the setting for range checking. */
+static void
+set_range_command(ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (STREQ(range,"on"))
+ {
+ range_check = range_check_on;
+ range_mode = range_mode_manual;
+ }
+ else if (STREQ(range,"warn"))
+ {
+ range_check = range_check_warn;
+ range_mode = range_mode_manual;
+ }
+ else if (STREQ(range,"off"))
+ {
+ range_check = range_check_off;
+ range_mode = range_mode_manual;
+ }
+ else if (STREQ(range,"auto"))
+ {
+ range_mode = range_mode_auto;
+ set_type_range();
+ /* Avoid hitting the set_range_str call below. We
+ did it in set_type_range. */
+ return;
+ }
+ set_range_str();
+ show_range_command((char *)0, from_tty);
+}
+
+/* Set the status of range and type checking based on
+ the current modes and the current language.
+ If SHOW is non-zero, then print out the current language,
+ type and range checking status. */
+static void
+set_type_range()
+{
+
+ if (range_mode == range_mode_auto)
+ range_check = current_language->la_range_check;
+
+ if (type_mode == type_mode_auto)
+ type_check = current_language->la_type_check;
+
+ set_type_str();
+ set_range_str();
+}
+
+/* Set current language to (enum language) LANG. */
+
+void
+set_language(lang)
+ enum language lang;
+{
+ int i;
+
+ for (i = 0; i < languages_size; i++) {
+ if (languages[i]->la_language == lang) {
+ current_language = languages[i];
+ set_type_range ();
+ set_lang_str();
+ break;
+ }
+ }
+}
+
+/* This page contains functions that update the global vars
+ language, type and range. */
+static void
+set_lang_str()
+{
+ char *prefix = "";
+
+ free (language);
+ if (language_mode == language_mode_auto)
+ prefix = "auto; currently ";
+
+ language = concat(prefix, current_language->la_name, NULL);
+}
+
+static void
+set_type_str()
+{
+ char *tmp, *prefix = "";
+
+ free (type);
+ if (type_mode==type_mode_auto)
+ prefix = "auto; currently ";
+
+ switch(type_check)
+ {
+ case type_check_on:
+ tmp = "on";
+ break;
+ case type_check_off:
+ tmp = "off";
+ break;
+ case type_check_warn:
+ tmp = "warn";
+ break;
+ default:
+ error ("Unrecognized type check setting.");
+ }
+
+ type = concat(prefix,tmp,NULL);
+}
+
+static void
+set_range_str()
+{
+ char *tmp, *pref = "";
+
+ free (range);
+ if (range_mode==range_mode_auto)
+ pref = "auto; currently ";
+
+ switch(range_check)
+ {
+ case range_check_on:
+ tmp = "on";
+ break;
+ case range_check_off:
+ tmp = "off";
+ break;
+ case range_check_warn:
+ tmp = "warn";
+ break;
+ default:
+ error ("Unrecognized range check setting.");
+ }
+
+ range = concat(pref,tmp,NULL);
+}
+
+
+/* Print out the current language settings: language, range and
+ type checking. If QUIETLY, print only what has changed. */
+
+void
+language_info (quietly)
+ int quietly;
+{
+ if (quietly && expected_language == current_language)
+ return;
+
+ expected_language = current_language;
+ printf("Current language: %s\n",language);
+ show_language_command((char *)0, 1);
+
+ if (!quietly)
+ {
+ printf("Type checking: %s\n",type);
+ show_type_command((char *)0, 1);
+ printf("Range checking: %s\n",range);
+ show_range_command((char *)0, 1);
+ }
+}
+
+/* Return the result of a binary operation. */
+
+#if 0 /* Currently unused */
+
+struct type *
+binop_result_type(v1,v2)
+ value v1,v2;
+{
+ int l1,l2,size,uns;
+
+ l1 = TYPE_LENGTH(VALUE_TYPE(v1));
+ l2 = TYPE_LENGTH(VALUE_TYPE(v2));
+
+ switch(current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ if (TYPE_CODE(VALUE_TYPE(v1))==TYPE_CODE_FLT)
+ return TYPE_CODE(VALUE_TYPE(v2)) == TYPE_CODE_FLT && l2 > l1 ?
+ VALUE_TYPE(v2) : VALUE_TYPE(v1);
+ else if (TYPE_CODE(VALUE_TYPE(v2))==TYPE_CODE_FLT)
+ return TYPE_CODE(VALUE_TYPE(v1)) == TYPE_CODE_FLT && l1 > l2 ?
+ VALUE_TYPE(v1) : VALUE_TYPE(v2);
+ else if (TYPE_UNSIGNED(VALUE_TYPE(v1)) && l1 > l2)
+ return VALUE_TYPE(v1);
+ else if (TYPE_UNSIGNED(VALUE_TYPE(v2)) && l2 > l1)
+ return VALUE_TYPE(v2);
+ else /* Both are signed. Result is the longer type */
+ return l1 > l2 ? VALUE_TYPE(v1) : VALUE_TYPE(v2);
+ break;
+ case language_m2:
+ /* If we are doing type-checking, l1 should equal l2, so this is
+ not needed. */
+ return l1 > l2 ? VALUE_TYPE(v1) : VALUE_TYPE(v2);
+ break;
+ case language_chill:
+ error ("Missing Chill support in function binop_result_check.");/*FIXME*/
+ }
+ abort();
+ return (struct type *)0; /* For lint */
+}
+
+#endif /* 0 */
+
+
+/* This page contains functions that return format strings for
+ printf for printing out numbers in different formats */
+
+/* Returns the appropriate printf format for hexadecimal
+ numbers. */
+char *
+local_hex_format_custom(pre)
+ char *pre;
+{
+ static char form[50];
+
+ strcpy (form, local_hex_format_prefix ());
+ strcat (form, "%");
+ strcat (form, pre);
+ strcat (form, local_hex_format_specifier ());
+ strcat (form, local_hex_format_suffix ());
+ return form;
+}
+
+/* Converts a number to hexadecimal and stores it in a static
+ string. Returns a pointer to this string. */
+char *
+local_hex_string (num)
+ unsigned long num;
+{
+ static char res[50];
+
+ sprintf (res, local_hex_format(), num);
+ return res;
+}
+
+/* Converts a number to custom hexadecimal and stores it in a static
+ string. Returns a pointer to this string. */
+char *
+local_hex_string_custom(num,pre)
+ unsigned long num;
+ char *pre;
+{
+ static char res[50];
+
+ sprintf (res, local_hex_format_custom(pre), num);
+ return res;
+}
+
+/* Returns the appropriate printf format for octal
+ numbers. */
+char *
+local_octal_format_custom(pre)
+ char *pre;
+{
+ static char form[50];
+
+ strcpy (form, local_octal_format_prefix ());
+ strcat (form, "%");
+ strcat (form, pre);
+ strcat (form, local_octal_format_specifier ());
+ strcat (form, local_octal_format_suffix ());
+ return form;
+}
+
+/* Returns the appropriate printf format for decimal numbers. */
+char *
+local_decimal_format_custom(pre)
+ char *pre;
+{
+ static char form[50];
+
+ strcpy (form, local_decimal_format_prefix ());
+ strcat (form, "%");
+ strcat (form, pre);
+ strcat (form, local_decimal_format_specifier ());
+ strcat (form, local_decimal_format_suffix ());
+ return form;
+}
+
+/* This page contains functions that are used in type/range checking.
+ They all return zero if the type/range check fails.
+
+ It is hoped that these will make extending GDB to parse different
+ languages a little easier. These are primarily used in eval.c when
+ evaluating expressions and making sure that their types are correct.
+ Instead of having a mess of conjucted/disjuncted expressions in an "if",
+ the ideas of type can be wrapped up in the following functions.
+
+ Note that some of them are not currently dependent upon which language
+ is currently being parsed. For example, floats are the same in
+ C and Modula-2 (ie. the only floating point type has TYPE_CODE of
+ TYPE_CODE_FLT), while booleans are different. */
+
+/* Returns non-zero if its argument is a simple type. This is the same for
+ both Modula-2 and for C. In the C case, TYPE_CODE_CHAR will never occur,
+ and thus will never cause the failure of the test. */
+int
+simple_type(type)
+ struct type *type;
+{
+ switch (TYPE_CODE (type)) {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Returns non-zero if its argument is of an ordered type.
+ An ordered type is one in which the elements can be tested for the
+ properties of "greater than", "less than", etc, or for which the
+ operations "increment" or "decrement" make sense. */
+int
+ordered_type (type)
+ struct type *type;
+{
+ switch (TYPE_CODE (type)) {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_RANGE:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Returns non-zero if the two types are the same */
+int
+same_type (arg1, arg2)
+ struct type *arg1, *arg2;
+{
+ if (structured_type(arg1) ? !structured_type(arg2) : structured_type(arg2))
+ /* One is structured and one isn't */
+ return 0;
+ else if (structured_type(arg1) && structured_type(arg2))
+ return arg1 == arg2;
+ else if (numeric_type(arg1) && numeric_type(arg2))
+ return (TYPE_CODE(arg2) == TYPE_CODE(arg1)) &&
+ (TYPE_UNSIGNED(arg1) == TYPE_UNSIGNED(arg2))
+ ? 1 : 0;
+ else
+ return arg1==arg2;
+}
+
+/* Returns non-zero if the type is integral */
+int
+integral_type (type)
+ struct type *type;
+{
+ switch(current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ return (TYPE_CODE(type) != TYPE_CODE_INT) &&
+ (TYPE_CODE(type) != TYPE_CODE_ENUM) ? 0 : 1;
+ case language_m2:
+ return TYPE_CODE(type) != TYPE_CODE_INT ? 0 : 1;
+ case language_chill:
+ error ("Missing Chill support in function integral_type."); /*FIXME*/
+ default:
+ error ("Language not supported.");
+ }
+}
+
+/* Returns non-zero if the value is numeric */
+int
+numeric_type (type)
+ struct type *type;
+{
+ switch (TYPE_CODE (type)) {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Returns non-zero if the value is a character type */
+int
+character_type (type)
+ struct type *type;
+{
+ switch(current_language->la_language)
+ {
+ case language_chill:
+ case language_m2:
+ return TYPE_CODE(type) != TYPE_CODE_CHAR ? 0 : 1;
+
+ case language_c:
+ case language_cplus:
+ return (TYPE_CODE(type) == TYPE_CODE_INT) &&
+ TYPE_LENGTH(type) == sizeof(char)
+ ? 1 : 0;
+ default:
+ return (0);
+ }
+}
+
+/* Returns non-zero if the value is a string type */
+int
+string_type (type)
+ struct type *type;
+{
+ switch(current_language->la_language)
+ {
+ case language_chill:
+ case language_m2:
+ return TYPE_CODE(type) != TYPE_CODE_STRING ? 0 : 1;
+
+ case language_c:
+ case language_cplus:
+ /* C does not have distinct string type. */
+ return (0);
+ default:
+ return (0);
+ }
+}
+
+/* Returns non-zero if the value is a boolean type */
+int
+boolean_type (type)
+ struct type *type;
+{
+ switch(current_language->la_language)
+ {
+ case language_chill:
+ case language_m2:
+ return TYPE_CODE(type) != TYPE_CODE_BOOL ? 0 : 1;
+
+ case language_c:
+ case language_cplus:
+ return TYPE_CODE(type) != TYPE_CODE_INT ? 0 : 1;
+ default:
+ return (0);
+ }
+}
+
+/* Returns non-zero if the value is a floating-point type */
+int
+float_type (type)
+ struct type *type;
+{
+ return TYPE_CODE(type) == TYPE_CODE_FLT;
+}
+
+/* Returns non-zero if the value is a pointer type */
+int
+pointer_type(type)
+ struct type *type;
+{
+ return TYPE_CODE(type) == TYPE_CODE_PTR ||
+ TYPE_CODE(type) == TYPE_CODE_REF;
+}
+
+/* Returns non-zero if the value is a structured type */
+int
+structured_type(type)
+ struct type *type;
+{
+ switch(current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ return (TYPE_CODE(type) == TYPE_CODE_STRUCT) ||
+ (TYPE_CODE(type) == TYPE_CODE_UNION) ||
+ (TYPE_CODE(type) == TYPE_CODE_ARRAY);
+ case language_m2:
+ return (TYPE_CODE(type) == TYPE_CODE_STRUCT) ||
+ (TYPE_CODE(type) == TYPE_CODE_SET) ||
+ (TYPE_CODE(type) == TYPE_CODE_ARRAY);
+ case language_chill:
+ error ("Missing Chill support in function structured_type."); /*FIXME*/
+ default:
+ return (0);
+ }
+}
+
+/* This page contains functions that return info about
+ (struct value) values used in GDB. */
+
+/* Returns non-zero if the value VAL represents a true value. */
+int
+value_true(val)
+ value val;
+{
+ int len, i;
+ struct type *type;
+ LONGEST v;
+
+ switch (current_language->la_language) {
+
+ case language_c:
+ case language_cplus:
+ return !value_logical_not (val);
+
+ case language_m2:
+ type = VALUE_TYPE(val);
+ if (TYPE_CODE (type) != TYPE_CODE_BOOL)
+ return 0; /* Not a BOOLEAN at all */
+ /* Search the fields for one that matches the current value. */
+ len = TYPE_NFIELDS (type);
+ v = value_as_long (val);
+ for (i = 0; i < len; i++)
+ {
+ QUIT;
+ if (v == TYPE_FIELD_BITPOS (type, i))
+ break;
+ }
+ if (i >= len)
+ return 0; /* Not a valid BOOLEAN value */
+ if (STREQ ("TRUE", TYPE_FIELD_NAME(VALUE_TYPE(val), i)))
+ return 1; /* BOOLEAN with value TRUE */
+ else
+ return 0; /* BOOLEAN with value FALSE */
+ break;
+
+ case language_chill:
+ error ("Missing Chill support in function value_type."); /*FIXME*/
+
+ default:
+ error ("Language not supported.");
+ }
+}
+
+/* Returns non-zero if the operator OP is defined on
+ the values ARG1 and ARG2. */
+
+#if 0 /* Currently unused */
+
+void
+binop_type_check(arg1,arg2,op)
+ value arg1,arg2;
+ int op;
+{
+ struct type *t1, *t2;
+
+ /* If we're not checking types, always return success. */
+ if (!STRICT_TYPE)
+ return;
+
+ t1=VALUE_TYPE(arg1);
+ if (arg2!=(value)NULL)
+ t2=VALUE_TYPE(arg2);
+ else
+ t2=NULL;
+
+ switch(op)
+ {
+ case BINOP_ADD:
+ case BINOP_SUB:
+ if ((numeric_type(t1) && pointer_type(t2)) ||
+ (pointer_type(t1) && numeric_type(t2)))
+ {
+ warning ("combining pointer and integer.\n");
+ break;
+ }
+ case BINOP_MUL:
+ case BINOP_LSH:
+ case BINOP_RSH:
+ if (!numeric_type(t1) || !numeric_type(t2))
+ type_op_error ("Arguments to %s must be numbers.",op);
+ else if (!same_type(t1,t2))
+ type_op_error ("Arguments to %s must be of the same type.",op);
+ break;
+
+ case BINOP_LOGICAL_AND:
+ case BINOP_LOGICAL_OR:
+ if (!boolean_type(t1) || !boolean_type(t2))
+ type_op_error ("Arguments to %s must be of boolean type.",op);
+ break;
+
+ case BINOP_EQUAL:
+ if ((pointer_type(t1) && !(pointer_type(t2) || integral_type(t2))) ||
+ (pointer_type(t2) && !(pointer_type(t1) || integral_type(t1))))
+ type_op_error ("A pointer can only be compared to an integer or pointer.",op);
+ else if ((pointer_type(t1) && integral_type(t2)) ||
+ (integral_type(t1) && pointer_type(t2)))
+ {
+ warning ("combining integer and pointer.\n");
+ break;
+ }
+ else if (!simple_type(t1) || !simple_type(t2))
+ type_op_error ("Arguments to %s must be of simple type.",op);
+ else if (!same_type(t1,t2))
+ type_op_error ("Arguments to %s must be of the same type.",op);
+ break;
+
+ case BINOP_REM:
+ case BINOP_MOD:
+ if (!integral_type(t1) || !integral_type(t2))
+ type_op_error ("Arguments to %s must be of integral type.",op);
+ break;
+
+ case BINOP_LESS:
+ case BINOP_GTR:
+ case BINOP_LEQ:
+ case BINOP_GEQ:
+ if (!ordered_type(t1) || !ordered_type(t2))
+ type_op_error ("Arguments to %s must be of ordered type.",op);
+ else if (!same_type(t1,t2))
+ type_op_error ("Arguments to %s must be of the same type.",op);
+ break;
+
+ case BINOP_ASSIGN:
+ if (pointer_type(t1) && !integral_type(t2))
+ type_op_error ("A pointer can only be assigned an integer.",op);
+ else if (pointer_type(t1) && integral_type(t2))
+ {
+ warning ("combining integer and pointer.");
+ break;
+ }
+ else if (!simple_type(t1) || !simple_type(t2))
+ type_op_error ("Arguments to %s must be of simple type.",op);
+ else if (!same_type(t1,t2))
+ type_op_error ("Arguments to %s must be of the same type.",op);
+ break;
+
+ case BINOP_CONCAT:
+ /* FIXME: Needs to handle bitstrings as well. */
+ if (!(string_type(t1) || character_type(t1) || integral_type(t1))
+ || !(string_type(t2) || character_type(t2) || integral_type(t2)))
+ type_op_error ("Arguments to %s must be strings or characters.", op);
+ break;
+
+ /* Unary checks -- arg2 is null */
+
+ case UNOP_LOGICAL_NOT:
+ if (!boolean_type(t1))
+ type_op_error ("Argument to %s must be of boolean type.",op);
+ break;
+
+ case UNOP_PLUS:
+ case UNOP_NEG:
+ if (!numeric_type(t1))
+ type_op_error ("Argument to %s must be of numeric type.",op);
+ break;
+
+ case UNOP_IND:
+ if (integral_type(t1))
+ {
+ warning ("combining pointer and integer.\n");
+ break;
+ }
+ else if (!pointer_type(t1))
+ type_op_error ("Argument to %s must be a pointer.",op);
+ break;
+
+ case UNOP_PREINCREMENT:
+ case UNOP_POSTINCREMENT:
+ case UNOP_PREDECREMENT:
+ case UNOP_POSTDECREMENT:
+ if (!ordered_type(t1))
+ type_op_error ("Argument to %s must be of an ordered type.",op);
+ break;
+
+ default:
+ /* Ok. The following operators have different meanings in
+ different languages. */
+ switch(current_language->la_language)
+ {
+#ifdef _LANG_c
+ case language_c:
+ case language_cplus:
+ switch(op)
+ {
+ case BINOP_DIV:
+ if (!numeric_type(t1) || !numeric_type(t2))
+ type_op_error ("Arguments to %s must be numbers.",op);
+ break;
+ }
+ break;
+#endif
+
+#ifdef _LANG_m2
+ case language_m2:
+ switch(op)
+ {
+ case BINOP_DIV:
+ if (!float_type(t1) || !float_type(t2))
+ type_op_error ("Arguments to %s must be floating point numbers.",op);
+ break;
+ case BINOP_INTDIV:
+ if (!integral_type(t1) || !integral_type(t2))
+ type_op_error ("Arguments to %s must be of integral type.",op);
+ break;
+ }
+#endif
+
+#ifdef _LANG_chill
+ case language_chill:
+ error ("Missing Chill support in function binop_type_check.");/*FIXME*/
+#endif
+
+ }
+ }
+}
+
+#endif /* 0 */
+
+
+/* This page contains functions for the printing out of
+ error messages that occur during type- and range-
+ checking. */
+
+/* Prints the format string FMT with the operator as a string
+ corresponding to the opcode OP. If FATAL is non-zero, then
+ this is an error and error () is called. Otherwise, it is
+ a warning and printf() is called. */
+void
+op_error (fmt,op,fatal)
+ char *fmt;
+ enum exp_opcode op;
+ int fatal;
+{
+ if (fatal)
+ error (fmt,op_string(op));
+ else
+ {
+ warning (fmt,op_string(op));
+ }
+}
+
+/* These are called when a language fails a type- or range-check.
+ The first argument should be a printf()-style format string, and
+ the rest of the arguments should be its arguments. If
+ [type|range]_check is [type|range]_check_on, then return_to_top_level()
+ is called in the style of error (). Otherwise, the message is prefixed
+ by the value of warning_pre_print and we do not return to the top level. */
+
+void
+type_error (va_alist)
+ va_dcl
+{
+ va_list args;
+ char *string;
+
+ if (type_check==type_check_warn)
+ fprintf(stderr,warning_pre_print);
+ else
+ target_terminal_ours();
+
+ va_start (args);
+ string = va_arg (args, char *);
+ vfprintf (stderr, string, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+ if (type_check==type_check_on)
+ return_to_top_level (RETURN_ERROR);
+}
+
+void
+range_error (va_alist)
+ va_dcl
+{
+ va_list args;
+ char *string;
+
+ if (range_check==range_check_warn)
+ fprintf(stderr,warning_pre_print);
+ else
+ target_terminal_ours();
+
+ va_start (args);
+ string = va_arg (args, char *);
+ vfprintf (stderr, string, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+ if (range_check==range_check_on)
+ return_to_top_level (RETURN_ERROR);
+}
+
+
+/* This page contains miscellaneous functions */
+
+/* Return the language struct for a given language enum. */
+
+const struct language_defn *
+language_def(lang)
+ enum language lang;
+{
+ int i;
+
+ for (i = 0; i < languages_size; i++) {
+ if (languages[i]->la_language == lang) {
+ return languages[i];
+ }
+ }
+ return NULL;
+}
+
+/* Return the language as a string */
+char *
+language_str(lang)
+ enum language lang;
+{
+ int i;
+
+ for (i = 0; i < languages_size; i++) {
+ if (languages[i]->la_language == lang) {
+ return languages[i]->la_name;
+ }
+ }
+ return "Unknown";
+}
+
+static void
+set_check (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ printf(
+"\"set check\" must be followed by the name of a check subcommand.\n");
+ help_list(setchecklist, "set check ", -1, stdout);
+}
+
+static void
+show_check (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ cmd_show_list(showchecklist, from_tty, "");
+}
+
+/* Add a language to the set of known languages. */
+
+void
+add_language (lang)
+ const struct language_defn *lang;
+{
+ if (lang->la_magic != LANG_MAGIC)
+ {
+ fprintf(stderr, "Magic number of %s language struct wrong\n",
+ lang->la_name);
+ abort();
+ }
+
+ if (!languages)
+ {
+ languages_allocsize = DEFAULT_ALLOCSIZE;
+ languages = (const struct language_defn **) xmalloc
+ (languages_allocsize * sizeof (*languages));
+ }
+ if (languages_size >= languages_allocsize)
+ {
+ languages_allocsize *= 2;
+ languages = (const struct language_defn **) xrealloc ((char *) languages,
+ languages_allocsize * sizeof (*languages));
+ }
+ languages[languages_size++] = lang;
+}
+
+/* Define the language that is no language. */
+
+static int
+unk_lang_parser ()
+{
+ return 1;
+}
+
+static void
+unk_lang_error (msg)
+ char *msg;
+{
+ error ("Attempted to parse an expression with unknown language");
+}
+
+static void
+unk_lang_printchar (c, stream)
+ register int c;
+ FILE *stream;
+{
+ error ("internal error - unimplemented function unk_lang_printchar called.");
+}
+
+static void
+unk_lang_printstr (stream, string, length, force_ellipses)
+ FILE *stream;
+ char *string;
+ unsigned int length;
+ int force_ellipses;
+{
+ error ("internal error - unimplemented function unk_lang_printstr called.");
+}
+
+static struct type *
+unk_lang_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ error ("internal error - unimplemented function unk_lang_create_fundamental_type called.");
+}
+
+void
+unk_lang_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ FILE *stream;
+ int show;
+ int level;
+{
+ error ("internal error - unimplemented function unk_lang_print_type called.");
+}
+
+int
+unk_lang_val_print (type, valaddr, address, stream, format, deref_ref,
+ recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ error ("internal error - unimplemented function unk_lang_val_print called.");
+}
+
+static struct type ** const (unknown_builtin_types[]) = { 0 };
+static const struct op_print unk_op_print_tab[] = {
+ {NULL, OP_NULL, PREC_NULL, 0}
+};
+
+const struct language_defn unknown_language_defn = {
+ "unknown",
+ language_unknown,
+ &unknown_builtin_types[0],
+ range_check_off,
+ type_check_off,
+ unk_lang_parser,
+ unk_lang_error,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ unk_lang_create_fundamental_type,
+ unk_lang_print_type, /* Print a type using appropriate syntax */
+ unk_lang_val_print, /* Print a value using appropriate syntax */
+ &builtin_type_error, /* longest signed integral type */
+ &builtin_type_error, /* longest unsigned integral type */
+ &builtin_type_error, /* longest floating point type */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ unk_op_print_tab, /* expression operators for printing */
+ LANG_MAGIC
+};
+
+/* These two structs define fake entries for the "local" and "auto" options. */
+const struct language_defn auto_language_defn = {
+ "auto",
+ language_auto,
+ &unknown_builtin_types[0],
+ range_check_off,
+ type_check_off,
+ unk_lang_parser,
+ unk_lang_error,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ unk_lang_create_fundamental_type,
+ unk_lang_print_type, /* Print a type using appropriate syntax */
+ unk_lang_val_print, /* Print a value using appropriate syntax */
+ &builtin_type_error, /* longest signed integral type */
+ &builtin_type_error, /* longest unsigned integral type */
+ &builtin_type_error, /* longest floating point type */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ unk_op_print_tab, /* expression operators for printing */
+ LANG_MAGIC
+};
+
+const struct language_defn local_language_defn = {
+ "local",
+ language_auto,
+ &unknown_builtin_types[0],
+ range_check_off,
+ type_check_off,
+ unk_lang_parser,
+ unk_lang_error,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ unk_lang_create_fundamental_type,
+ unk_lang_print_type, /* Print a type using appropriate syntax */
+ unk_lang_val_print, /* Print a value using appropriate syntax */
+ &builtin_type_error, /* longest signed integral type */
+ &builtin_type_error, /* longest unsigned integral type */
+ &builtin_type_error, /* longest floating point type */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ unk_op_print_tab, /* expression operators for printing */
+ LANG_MAGIC
+};
+
+/* Initialize the language routines */
+
+void
+_initialize_language()
+{
+ struct cmd_list_element *set, *show;
+
+ /* GDB commands for language specific stuff */
+
+ set = add_set_cmd ("language", class_support, var_string_noescape,
+ (char *)&language,
+ "Set the current source language.",
+ &setlist);
+ show = add_show_from_set (set, &showlist);
+ set->function.cfunc = set_language_command;
+ show->function.cfunc = show_language_command;
+
+ add_prefix_cmd ("check", no_class, set_check,
+ "Set the status of the type/range checker",
+ &setchecklist, "set check ", 0, &setlist);
+ add_alias_cmd ("c", "check", no_class, 1, &setlist);
+ add_alias_cmd ("ch", "check", no_class, 1, &setlist);
+
+ add_prefix_cmd ("check", no_class, show_check,
+ "Show the status of the type/range checker",
+ &showchecklist, "show check ", 0, &showlist);
+ add_alias_cmd ("c", "check", no_class, 1, &showlist);
+ add_alias_cmd ("ch", "check", no_class, 1, &showlist);
+
+ set = add_set_cmd ("type", class_support, var_string_noescape,
+ (char *)&type,
+ "Set type checking. (on/warn/off/auto)",
+ &setchecklist);
+ show = add_show_from_set (set, &showchecklist);
+ set->function.cfunc = set_type_command;
+ show->function.cfunc = show_type_command;
+
+ set = add_set_cmd ("range", class_support, var_string_noescape,
+ (char *)&range,
+ "Set range checking. (on/warn/off/auto)",
+ &setchecklist);
+ show = add_show_from_set (set, &showchecklist);
+ set->function.cfunc = set_range_command;
+ show->function.cfunc = show_range_command;
+
+ add_language (&unknown_language_defn);
+ add_language (&local_language_defn);
+ add_language (&auto_language_defn);
+
+ language = savestring ("auto",strlen("auto"));
+ range = savestring ("auto",strlen("auto"));
+ type = savestring ("auto",strlen("auto"));
+
+ /* Have the above take effect */
+
+ set_language_command (language, 0);
+ set_type_command (NULL, 0);
+ set_range_command (NULL, 0);
+}
diff --git a/gnu/usr.bin/gdb/gdb/language.h b/gnu/usr.bin/gdb/gdb/language.h
new file mode 100644
index 000000000000..9df5345c9301
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/language.h
@@ -0,0 +1,413 @@
+/* Source-language-related definitions for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Contributed by the Department of Computer Science at the State University
+ of New York at Buffalo.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (LANGUAGE_H)
+#define LANGUAGE_H 1
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct value;
+struct objfile;
+/* enum exp_opcode; ANSI's `wisdom' didn't include forward enum decls. */
+#endif
+
+/* This used to be included to configure GDB for one or more specific
+ languages. Now it is shortcutted to configure for all of them. FIXME. */
+/* #include "lang_def.h" */
+#define _LANG_c
+#define _LANG_m2
+#define _LANG_chill
+
+/* range_mode ==
+ range_mode_auto: range_check set automatically to default of language.
+ range_mode_manual: range_check set manually by user. */
+
+extern enum range_mode {range_mode_auto, range_mode_manual} range_mode;
+
+/* range_check ==
+ range_check_on: Ranges are checked in GDB expressions, producing errors.
+ range_check_warn: Ranges are checked, producing warnings.
+ range_check_off: Ranges are not checked in GDB expressions. */
+
+extern enum range_check
+ {range_check_off, range_check_warn, range_check_on} range_check;
+
+/* type_mode ==
+ type_mode_auto: type_check set automatically to default of language
+ type_mode_manual: type_check set manually by user. */
+
+extern enum type_mode {type_mode_auto, type_mode_manual} type_mode;
+
+/* type_check ==
+ type_check_on: Types are checked in GDB expressions, producing errors.
+ type_check_warn: Types are checked, producing warnings.
+ type_check_off: Types are not checked in GDB expressions. */
+
+extern enum type_check
+ {type_check_off, type_check_warn, type_check_on} type_check;
+
+/* Information for doing language dependent formatting of printed values. */
+
+struct language_format_info
+{
+ /* The format that can be passed directly to standard C printf functions
+ to generate a completely formatted value in the format appropriate for
+ the language. */
+
+ char *la_format;
+
+ /* The prefix to be used when directly printing a value, or constructing
+ a standard C printf format. This generally is everything up to the
+ conversion specification (the part introduced by the '%' character
+ and terminated by the conversion specifier character). */
+
+ char *la_format_prefix;
+
+ /* The conversion specifier. This is generally everything after the
+ field width and precision, typically only a single character such
+ as 'o' for octal format or 'x' for hexadecimal format. */
+
+ char *la_format_specifier;
+
+ /* The suffix to be used when directly printing a value, or constructing
+ a standard C printf format. This generally is everything after the
+ conversion specification (the part introduced by the '%' character
+ and terminated by the conversion specifier character). */
+
+ char *la_format_suffix; /* Suffix for custom format string */
+};
+
+/* Structure tying together assorted information about a language. */
+
+struct language_defn
+{
+ /* Name of the language */
+
+ char *la_name;
+
+ /* its symtab language-enum (defs.h) */
+
+ enum language la_language;
+
+ /* Its builtin types */
+
+ struct type ** const *la_builtin_type_vector;
+
+ /* Default range checking */
+
+ enum range_check la_range_check;
+
+ /* Default type checking */
+
+ enum type_check la_type_check;
+
+ /* Parser function. */
+
+ int (*la_parser) PARAMS((void));
+
+ /* Parser error function */
+
+ void (*la_error) PARAMS ((char *));
+
+ void (*la_printchar) PARAMS ((int, FILE *));
+
+ void (*la_printstr) PARAMS ((FILE *, char *, unsigned int, int));
+
+ struct type *(*la_fund_type) PARAMS ((struct objfile *, int));
+
+ /* Print a type using syntax appropriate for this language. */
+
+ void (*la_print_type) PARAMS ((struct type *, char *, FILE *, int, int));
+
+ /* Print a value using syntax appropriate for this language. */
+
+ int (*la_val_print) PARAMS ((struct type *, char *, CORE_ADDR, FILE *,
+ int, int, int, enum val_prettyprint));
+
+ /* Longest signed integral type */
+
+ struct type **la_longest_int;
+
+ /* Longest unsigned integral type */
+
+ struct type **la_longest_unsigned_int;
+
+ /* Longest floating point type */
+
+ struct type **la_longest_float;
+
+ /* Base 2 (binary) formats. */
+
+ struct language_format_info la_binary_format;
+
+ /* Base 8 (octal) formats. */
+
+ struct language_format_info la_octal_format;
+
+ /* Base 10 (decimal) formats */
+
+ struct language_format_info la_decimal_format;
+
+ /* Base 16 (hexadecimal) formats */
+
+ struct language_format_info la_hex_format;
+
+
+ /* Table for printing expressions */
+
+ const struct op_print *la_op_print_tab;
+
+ /* Add fields above this point, so the magic number is always last. */
+ /* Magic number for compat checking */
+
+ long la_magic;
+
+};
+
+#define LANG_MAGIC 910823L
+
+/* Pointer to the language_defn for our current language. This pointer
+ always points to *some* valid struct; it can be used without checking
+ it for validity.
+
+ The current language affects expression parsing and evaluation
+ (FIXME: it might be cleaner to make the evaluation-related stuff
+ separate exp_opcodes for each different set of semantics. We
+ should at least think this through more clearly with respect to
+ what happens if the language is changed between parsing and
+ evaluation) and printing of things like types and arrays. It does
+ *not* affect symbol-reading-- each source file in a symbol-file has
+ its own language and we should keep track of that regardless of the
+ language when symbols are read. If we want some manual setting for
+ the language of symbol files (e.g. detecting when ".c" files are
+ C++), it should be a seprate setting from the current_language. */
+
+extern const struct language_defn *current_language;
+
+/* Pointer to the language_defn expected by the user, e.g. the language
+ of main(), or the language we last mentioned in a message, or C. */
+
+extern const struct language_defn *expected_language;
+
+/* language_mode ==
+ language_mode_auto: current_language automatically set upon selection
+ of scope (e.g. stack frame)
+ language_mode_manual: current_language set only by user. */
+
+extern enum language_mode
+ {language_mode_auto, language_mode_manual} language_mode;
+
+/* These macros define the behaviour of the expression
+ evaluator. */
+
+/* Should we strictly type check expressions? */
+#define STRICT_TYPE (type_check != type_check_off)
+
+/* Should we range check values against the domain of their type? */
+#define RANGE_CHECK (range_check != range_check_off)
+
+/* "cast" really means conversion */
+/* FIXME -- should be a setting in language_defn */
+#define CAST_IS_CONVERSION (current_language->la_language == language_c || \
+ current_language->la_language == language_cplus)
+
+extern void
+language_info PARAMS ((int));
+
+extern void
+set_language PARAMS ((enum language));
+
+
+/* This page contains functions that return things that are
+ specific to languages. Each of these functions is based on
+ the current setting of working_lang, which the user sets
+ with the "set language" command. */
+
+/* Returns some built-in types */
+#define longest_int() (*current_language->la_longest_int)
+#define longest_unsigned_int() (*current_language->la_longest_unsigned_int)
+#define longest_float() (*current_language->la_longest_float)
+
+#define create_fundamental_type(objfile,typeid) \
+ (current_language->la_fund_type(objfile, typeid))
+
+#define LA_PRINT_TYPE(type,varstring,stream,show,level) \
+ (current_language->la_print_type(type,varstring,stream,show,level))
+
+#define LA_VAL_PRINT(type,valaddr,addr,stream,fmt,deref,recurse,pretty) \
+ (current_language->la_val_print(type,valaddr,addr,stream,fmt,deref, \
+ recurse,pretty))
+
+/* Return a format string for printf that will print a number in one of
+ the local (language-specific) formats. Result is static and is
+ overwritten by the next call. Takes printf options like "08" or "l"
+ (to produce e.g. %08x or %lx). */
+
+#define local_binary_format() \
+ (current_language->la_binary_format.la_format)
+#define local_binary_format_prefix() \
+ (current_language->la_binary_format.la_format_prefix)
+#define local_binary_format_specifier() \
+ (current_language->la_binary_format.la_format_specifier)
+#define local_binary_format_suffix() \
+ (current_language->la_binary_format.la_format_suffix)
+
+#define local_octal_format() \
+ (current_language->la_octal_format.la_format)
+#define local_octal_format_prefix() \
+ (current_language->la_octal_format.la_format_prefix)
+#define local_octal_format_specifier() \
+ (current_language->la_octal_format.la_format_specifier)
+#define local_octal_format_suffix() \
+ (current_language->la_octal_format.la_format_suffix)
+
+#define local_decimal_format() \
+ (current_language->la_decimal_format.la_format)
+#define local_decimal_format_prefix() \
+ (current_language->la_decimal_format.la_format_prefix)
+#define local_decimal_format_specifier() \
+ (current_language->la_decimal_format.la_format_specifier)
+#define local_decimal_format_suffix() \
+ (current_language->la_decimal_format.la_format_suffix)
+
+#define local_hex_format() \
+ (current_language->la_hex_format.la_format)
+#define local_hex_format_prefix() \
+ (current_language->la_hex_format.la_format_prefix)
+#define local_hex_format_specifier() \
+ (current_language->la_hex_format.la_format_specifier)
+#define local_hex_format_suffix() \
+ (current_language->la_hex_format.la_format_suffix)
+
+#define LA_PRINT_CHAR(ch, stream) \
+ (current_language->la_printchar(ch, stream))
+#define LA_PRINT_STRING(stream, string, length, force_ellipses) \
+ (current_language->la_printstr(stream, string, length, force_ellipses))
+
+/* Test a character to decide whether it can be printed in literal form
+ or needs to be printed in another representation. For example,
+ in C the literal form of the character with octal value 141 is 'a'
+ and the "other representation" is '\141'. The "other representation"
+ is program language dependent. */
+
+#define PRINT_LITERAL_FORM(c) \
+ ((c)>=0x20 && ((c)<0x7F || (c)>=0xA0) && (!sevenbit_strings || (c)<0x80))
+
+/* Return a format string for printf that will print a number in one of
+ the local (language-specific) formats. Result is static and is
+ overwritten by the next call. Takes printf options like "08" or "l"
+ (to produce e.g. %08x or %lx). */
+
+extern char *
+local_decimal_format_custom PARAMS ((char *)); /* language.c */
+
+extern char *
+local_octal_format_custom PARAMS ((char *)); /* language.c */
+
+extern char *
+local_hex_format_custom PARAMS ((char *)); /* language.c */
+
+/* Return a string that contains a number formatted in one of the local
+ (language-specific) formats. Result is static and is overwritten by
+ the next call. Takes printf options like "08" or "l". */
+
+extern char *
+local_hex_string PARAMS ((unsigned long)); /* language.c */
+
+extern char *
+local_hex_string_custom PARAMS ((unsigned long, char *)); /* language.c */
+
+/* Type predicates */
+
+extern int
+simple_type PARAMS ((struct type *));
+
+extern int
+ordered_type PARAMS ((struct type *));
+
+extern int
+same_type PARAMS ((struct type *, struct type *));
+
+extern int
+integral_type PARAMS ((struct type *));
+
+extern int
+numeric_type PARAMS ((struct type *));
+
+extern int
+character_type PARAMS ((struct type *));
+
+extern int
+boolean_type PARAMS ((struct type *));
+
+extern int
+float_type PARAMS ((struct type *));
+
+extern int
+pointer_type PARAMS ((struct type *));
+
+extern int
+structured_type PARAMS ((struct type *));
+
+/* Checks Binary and Unary operations for semantic type correctness */
+/* FIXME: Does not appear to be used */
+#define unop_type_check(v,o) binop_type_check((v),NULL,(o))
+
+extern void
+binop_type_check PARAMS ((struct value *, struct value *, int));
+
+/* Error messages */
+
+extern void
+op_error PARAMS ((char *fmt, enum exp_opcode, int));
+
+#define type_op_error(f,o) \
+ op_error((f),(o),type_check==type_check_on ? 1 : 0)
+#define range_op_error(f,o) \
+ op_error((f),(o),range_check==range_check_on ? 1 : 0)
+
+extern void
+type_error ();
+
+void
+range_error ();
+
+/* Data: Does this value represent "truth" to the current language? */
+
+extern int
+value_true PARAMS ((struct value *));
+
+/* Misc: The string representing a particular enum language. */
+
+extern const struct language_defn *
+language_def PARAMS ((enum language));
+
+extern char *
+language_str PARAMS ((enum language));
+
+/* Add a language to the set known by GDB (at initialization time). */
+
+extern void
+add_language PARAMS ((const struct language_defn *));
+
+extern enum language
+get_frame_language PARAMS ((void)); /* In stack.c */
+
+#endif /* defined (LANGUAGE_H) */
diff --git a/gnu/usr.bin/gdb/gdb/m2-exp.y b/gnu/usr.bin/gdb/gdb/m2-exp.y
new file mode 100644
index 000000000000..cc4001fa984c
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/m2-exp.y
@@ -0,0 +1,1169 @@
+/* YACC grammar for Modula-2 expressions, for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+ Generated from expread.y (now c-exp.y) and contributed by the Department
+ of Computer Science at the State University of New York at Buffalo, 1991.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Parse a Modula-2 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.
+
+ Note that malloc's and realloc's in this file are transformed to
+ xmalloc and xrealloc respectively by the same sed command in the
+ makefile that remaps any other malloc/realloc inserted by the parser
+ generator. Doing this with #defines and trying to control the interaction
+ with include files (<malloc.h> and <stdlib.h> for example) just became
+ too messy, particularly when such includes can be inserted at random
+ times by the parser generator. */
+
+%{
+
+#include "defs.h"
+#include "expression.h"
+#include "language.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "m2-lang.h"
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth m2_maxdepth
+#define yyparse m2_parse
+#define yylex m2_lex
+#define yyerror m2_error
+#define yylval m2_lval
+#define yychar m2_char
+#define yydebug m2_debug
+#define yypact m2_pact
+#define yyr1 m2_r1
+#define yyr2 m2_r2
+#define yydef m2_def
+#define yychk m2_chk
+#define yypgo m2_pgo
+#define yyact m2_act
+#define yyexca m2_exca
+#define yyerrflag m2_errflag
+#define yynerrs m2_nerrs
+#define yyps m2_ps
+#define yypv m2_pv
+#define yys m2_s
+#define yy_yys m2_yys
+#define yystate m2_state
+#define yytmp m2_tmp
+#define yyv m2_v
+#define yy_yyv m2_yyv
+#define yyval m2_val
+#define yylloc m2_lloc
+#define yyreds m2_reds /* With YYDEBUG defined */
+#define yytoks m2_toks /* With YYDEBUG defined */
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+#if 0
+static char *
+make_qualname PARAMS ((char *, char *));
+#endif
+
+static int
+parse_number PARAMS ((int));
+
+/* The sign of the number being parsed. */
+static int number_sign = 1;
+
+/* The block that the module specified by the qualifer on an identifer is
+ contained in, */
+#if 0
+static struct block *modblock=0;
+#endif
+
+%}
+
+/* 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;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ }
+
+%type <voidval> exp type_exp start set
+%type <voidval> variable
+%type <tval> type
+%type <bval> block
+%type <sym> fblock
+
+%token <lval> INT HEX ERROR
+%token <ulval> UINT M2_TRUE M2_FALSE CHAR
+%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 <sval> NAME BLOCKNAME IDENT VARNAME
+%token <sval> TYPENAME
+
+%token SIZE CAP ORD HIGH ABS MIN_FUNC MAX_FUNC FLOAT_FUNC VAL CHR ODD TRUNC
+%token INC DEC INCL EXCL
+
+/* The GDB scope operator */
+%token COLONCOLON
+
+%token <lval> LAST REGNAME
+
+%token <ivar> INTERNAL_VAR
+
+/* M2 tokens */
+%left ','
+%left ABOVE_COMMA
+%nonassoc ASSIGN
+%left '<' '>' LEQ GEQ '=' NOTEQUAL '#' IN
+%left OROR
+%left LOGICAL_AND '&'
+%left '@'
+%left '+' '-'
+%left '*' '/' DIV MOD
+%right UNARY
+%right '^' DOT '[' '('
+%right NOT '~'
+%left COLONCOLON QID
+/* This is not an actual token ; it is used for precedence.
+%right QID
+*/
+
+
+%%
+
+start : exp
+ | type_exp
+ ;
+
+type_exp: type
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE);
+ }
+ ;
+
+/* Expressions */
+
+exp : exp '^' %prec UNARY
+ { write_exp_elt_opcode (UNOP_IND); }
+
+exp : '-'
+ { number_sign = -1; }
+ exp %prec UNARY
+ { number_sign = 1;
+ write_exp_elt_opcode (UNOP_NEG); }
+ ;
+
+exp : '+' exp %prec UNARY
+ { write_exp_elt_opcode(UNOP_PLUS); }
+ ;
+
+exp : not_exp exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+ ;
+
+not_exp : NOT
+ | '~'
+ ;
+
+exp : CAP '(' exp ')'
+ { write_exp_elt_opcode (UNOP_CAP); }
+ ;
+
+exp : ORD '(' exp ')'
+ { write_exp_elt_opcode (UNOP_ORD); }
+ ;
+
+exp : ABS '(' exp ')'
+ { write_exp_elt_opcode (UNOP_ABS); }
+ ;
+
+exp : HIGH '(' exp ')'
+ { write_exp_elt_opcode (UNOP_HIGH); }
+ ;
+
+exp : MIN_FUNC '(' type ')'
+ { write_exp_elt_opcode (UNOP_MIN);
+ write_exp_elt_type ($3);
+ write_exp_elt_opcode (UNOP_MIN); }
+ ;
+
+exp : MAX_FUNC '(' type ')'
+ { write_exp_elt_opcode (UNOP_MAX);
+ write_exp_elt_type ($3);
+ write_exp_elt_opcode (UNOP_MIN); }
+ ;
+
+exp : FLOAT_FUNC '(' exp ')'
+ { write_exp_elt_opcode (UNOP_FLOAT); }
+ ;
+
+exp : VAL '(' type ',' exp ')'
+ { write_exp_elt_opcode (BINOP_VAL);
+ write_exp_elt_type ($3);
+ write_exp_elt_opcode (BINOP_VAL); }
+ ;
+
+exp : CHR '(' exp ')'
+ { write_exp_elt_opcode (UNOP_CHR); }
+ ;
+
+exp : ODD '(' exp ')'
+ { write_exp_elt_opcode (UNOP_ODD); }
+ ;
+
+exp : TRUNC '(' exp ')'
+ { write_exp_elt_opcode (UNOP_TRUNC); }
+ ;
+
+exp : SIZE exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ ;
+
+
+exp : INC '(' exp ')'
+ { write_exp_elt_opcode(UNOP_PREINCREMENT); }
+ ;
+
+exp : INC '(' exp ',' exp ')'
+ { write_exp_elt_opcode(BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode(BINOP_ADD);
+ write_exp_elt_opcode(BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : DEC '(' exp ')'
+ { write_exp_elt_opcode(UNOP_PREDECREMENT);}
+ ;
+
+exp : DEC '(' exp ',' exp ')'
+ { write_exp_elt_opcode(BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode(BINOP_SUB);
+ write_exp_elt_opcode(BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : exp DOT NAME
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+ ;
+
+exp : set
+ ;
+
+exp : exp IN set
+ { error("Sets are not implemented.");}
+ ;
+
+exp : INCL '(' exp ',' exp ')'
+ { error("Sets are not implemented.");}
+ ;
+
+exp : EXCL '(' exp ',' exp ')'
+ { error("Sets are not implemented.");}
+
+set : '{' arglist '}'
+ { error("Sets are not implemented.");}
+ | type '{' arglist '}'
+ { error("Sets are not implemented.");}
+ ;
+
+
+/* Modula-2 array subscript notation [a,b,c...] */
+exp : exp '['
+ /* This function just saves the number of arguments
+ that follow in the list. It is *not* specific to
+ function types */
+ { start_arglist(); }
+ non_empty_arglist ']' %prec DOT
+ { write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst ((LONGEST) end_arglist());
+ write_exp_elt_opcode (MULTI_SUBSCRIPT); }
+ ;
+
+exp : exp '('
+ /* This is to save the value of arglist_len
+ being accumulated by an outer function call. */
+ { start_arglist (); }
+ arglist ')' %prec DOT
+ { 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++; }
+ ;
+
+non_empty_arglist
+ : exp
+ { arglist_len = 1; }
+ ;
+
+non_empty_arglist
+ : non_empty_arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+/* GDB construct */
+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 ($1);
+ write_exp_elt_opcode (UNOP_CAST); }
+ ;
+
+exp : '(' exp ')'
+ { }
+ ;
+
+/* Binary operators in order of decreasing precedence. Note that some
+ of these operators are overloaded! (ie. sets) */
+
+/* GDB construct */
+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 DIV exp
+ { write_exp_elt_opcode (BINOP_INTDIV); }
+ ;
+
+exp : exp MOD 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 '=' exp
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+ ;
+
+exp : exp NOTEQUAL exp
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+ | exp '#' 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 LOGICAL_AND exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+ ;
+
+exp : exp OROR exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+ ;
+
+exp : exp ASSIGN exp
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+ ;
+
+
+/* Constants */
+
+exp : M2_TRUE
+ { write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_BOOL); }
+ ;
+
+exp : M2_FALSE
+ { write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_BOOL); }
+ ;
+
+exp : INT
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_int);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : UINT
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_card);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ ;
+
+exp : CHAR
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_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_m2_real);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+/* The GDB internal variable $$, et al. */
+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 : SIZE '(' 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_M2_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_M2_STRING); }
+ ;
+
+/* This will be used for extensions later. Like adding modules. */
+block : fblock
+ { $$ = SYMBOL_BLOCK_VALUE($1); }
+ ;
+
+fblock : BLOCKNAME
+ { struct symbol *sym
+ = lookup_symbol (copy_name ($1), expression_context_block,
+ VAR_NAMESPACE, 0, NULL);
+ $$ = sym;}
+ ;
+
+
+/* GDB scope operator */
+fblock : block COLONCOLON BLOCKNAME
+ { 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));
+ $$ = tem;
+ }
+ ;
+
+/* Useful for assigning to PROCEDURE variables */
+variable: fblock
+ { write_exp_elt_opcode(OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym ($1);
+ write_exp_elt_opcode (OP_VAR_VALUE); }
+ ;
+
+/* GDB internal ($foo) variable */
+variable: INTERNAL_VAR
+ { write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern ($1);
+ write_exp_elt_opcode (OP_INTERNALVAR); }
+ ;
+
+/* GDB scope operator */
+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);
+ /* block_found is set by lookup_symbol. */
+ write_exp_elt_block (block_found);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); }
+ ;
+
+/* Base case for variables. */
+variable: NAME
+ { struct symbol *sym;
+ int is_a_field_of_this;
+
+ sym = lookup_symbol (copy_name ($1),
+ expression_context_block,
+ VAR_NAMESPACE,
+ &is_a_field_of_this,
+ NULL);
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name ($1);
+
+ msymbol = lookup_minimal_symbol (arg,
+ (struct objfile *) NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_long);
+ write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ if (msymbol -> type == mst_data ||
+ msymbol -> type == mst_bss)
+ write_exp_elt_type (builtin_type_int);
+ else if (msymbol -> type == mst_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 (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name ($1));
+ }
+ }
+ ;
+
+type
+ : TYPENAME
+ { $$ = lookup_typename (copy_name ($1),
+ expression_context_block, 0); }
+
+ ;
+
+%%
+
+#if 0 /* FIXME! */
+int
+overflow(a,b)
+ long a,b;
+{
+ return (MAX_OF_TYPE(builtin_type_m2_int) - b) < a;
+}
+
+int
+uoverflow(a,b)
+ unsigned long a,b;
+{
+ return (MAX_OF_TYPE(builtin_type_m2_card) - b) < a;
+}
+#endif /* FIXME */
+
+/* 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 (olen)
+ int olen;
+{
+ register char *p = lexptr;
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ register int c,i,ischar=0;
+ register int base = input_radix;
+ register int len = olen;
+ int unsigned_p = number_sign == 1 ? 1 : 0;
+
+ if(p[len-1] == 'H')
+ {
+ base = 16;
+ len--;
+ }
+ else if(p[len-1] == 'C' || p[len-1] == 'B')
+ {
+ base = 8;
+ ischar = p[len-1] == 'C';
+ len--;
+ }
+
+ /* Scan the number */
+ for (c = 0; c < len; c++)
+ {
+ if (p[c] == '.' && base == 10)
+ {
+ /* It's a float since it contains a point. */
+ yylval.dval = atof (p);
+ lexptr += len;
+ return FLOAT;
+ }
+ if (p[c] == '.' && base != 10)
+ error("Floating point numbers must be base 10.");
+ if (base == 10 && (p[c] < '0' || p[c] > '9'))
+ error("Invalid digit \'%c\' in number.",p[c]);
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ n *= base;
+ if( base == 8 && (c == '8' || c == '9'))
+ error("Invalid digit \'%c\' in octal number.",c);
+ if (c >= '0' && c <= '9')
+ i = c - '0';
+ else
+ {
+ if (base == 16 && c >= 'A' && c <= 'F')
+ i = c - 'A' + 10;
+ else
+ return ERROR;
+ }
+ n+=i;
+ if(i >= base)
+ return ERROR;
+ if(!unsigned_p && number_sign == 1 && (prevn >= n))
+ unsigned_p=1; /* Try something unsigned */
+ /* Don't do the range check if n==i and i==0, since that special
+ case will give an overflow error. */
+ if(RANGE_CHECK && n!=i && i)
+ {
+ if((unsigned_p && (unsigned)prevn >= (unsigned)n) ||
+ ((!unsigned_p && number_sign==-1) && -prevn <= -n))
+ range_error("Overflow on numeric constant.");
+ }
+ prevn=n;
+ }
+
+ lexptr = p;
+ if(*p == 'B' || *p == 'C' || *p == 'H')
+ lexptr++; /* Advance past B,C or H */
+
+ if (ischar)
+ {
+ yylval.ulval = n;
+ return CHAR;
+ }
+ else if ( unsigned_p && number_sign == 1)
+ {
+ yylval.ulval = n;
+ return UINT;
+ }
+ else if((unsigned_p && (n<0))) {
+ range_error("Overflow on numeric constant -- number too large.");
+ /* But, this can return if range_check == range_warn. */
+ }
+ yylval.lval = n;
+ return INT;
+}
+
+
+/* Some tokens */
+
+static struct
+{
+ char name[2];
+ int token;
+} tokentab2[] =
+{
+ { {'<', '>'}, NOTEQUAL },
+ { {':', '='}, ASSIGN },
+ { {'<', '='}, LEQ },
+ { {'>', '='}, GEQ },
+ { {':', ':'}, COLONCOLON },
+
+};
+
+/* Some specific keywords */
+
+struct keyword {
+ char keyw[10];
+ int token;
+};
+
+static struct keyword keytab[] =
+{
+ {"OR" , OROR },
+ {"IN", IN },/* Note space after IN */
+ {"AND", LOGICAL_AND},
+ {"ABS", ABS },
+ {"CHR", CHR },
+ {"DEC", DEC },
+ {"NOT", NOT },
+ {"DIV", DIV },
+ {"INC", INC },
+ {"MAX", MAX_FUNC },
+ {"MIN", MIN_FUNC },
+ {"MOD", MOD },
+ {"ODD", ODD },
+ {"CAP", CAP },
+ {"ORD", ORD },
+ {"VAL", VAL },
+ {"EXCL", EXCL },
+ {"HIGH", HIGH },
+ {"INCL", INCL },
+ {"SIZE", SIZE },
+ {"FLOAT", FLOAT_FUNC },
+ {"TRUNC", TRUNC },
+};
+
+
+/* Read one token, getting characters through lexptr. */
+
+/* This is where we will check to make sure that the language and the operators used are
+ compatible */
+
+static int
+yylex ()
+{
+ register int c;
+ register int namelen;
+ register int i;
+ register char *tokstart;
+ register char quote;
+
+ retry:
+
+ tokstart = lexptr;
+
+
+ /* See if it is a special token of length 2 */
+ for( i = 0 ; i < sizeof tokentab2 / sizeof tokentab2[0] ; i++)
+ if(STREQN(tokentab2[i].name, tokstart, 2))
+ {
+ lexptr += 2;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ 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')
+ break; /* Falls into number code. */
+ else
+ {
+ lexptr++;
+ return DOT;
+ }
+
+/* These are character tokens that appear as-is in the YACC grammar */
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '^':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '=':
+ case '{':
+ case '}':
+ case '#':
+ case '@':
+ case '~':
+ case '&':
+ lexptr++;
+ return c;
+
+ case '\'' :
+ case '"':
+ quote = c;
+ for (namelen = 1; (c = tokstart[namelen]) != quote && c != '\0'; namelen++)
+ if (c == '\\')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ c = tokstart[++namelen];
+ }
+ }
+ if(c != quote)
+ error("Unterminated string or character constant.");
+ yylval.sval.ptr = tokstart + 1;
+ yylval.sval.length = namelen - 1;
+ lexptr += namelen + 1;
+
+ if(namelen == 2) /* Single character */
+ {
+ yylval.ulval = tokstart[1];
+ return CHAR;
+ }
+ else
+ return STRING;
+ }
+
+ /* Is it a number? */
+ /* Note: We have already dealt with the case of the token '.'.
+ See case '.' above. */
+ if ((c >= '0' && c <= '9'))
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0;
+ register char *p = tokstart;
+ int toktype;
+
+ for (++p ;; ++p)
+ {
+ if (!got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!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;
+ else if ((*p < '0' || *p > '9') &&
+ (*p < 'A' || *p > 'F') &&
+ (*p != 'H')) /* Modula-2 hexadecimal number */
+ break;
+ }
+ toktype = parse_number (p - tokstart);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ memcpy (err_copy, tokstart, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ 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])
+ && STREQN (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)
+ && STREQN (tokstart + 1, std_regs[c].name, namelen - 1))
+ {
+ yylval.lval = std_regs[c].regnum;
+ return REGNAME;
+ }
+ }
+
+
+ /* Lookup special keywords */
+ for(i = 0 ; i < sizeof(keytab) / sizeof(keytab[0]) ; i++)
+ if(namelen == strlen(keytab[i].keyw) && STREQN(tokstart,keytab[i].keyw,namelen))
+ return keytab[i].token;
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ /* Any other names starting in $ are debugger internal variables. */
+
+ if (*tokstart == '$')
+ {
+ yylval.ivar = (struct internalvar *) lookup_internalvar (copy_name (yylval.sval) + 1);
+ return INTERNAL_VAR;
+ }
+
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions. 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;
+
+ if (lookup_partial_symtab (tmp))
+ return BLOCKNAME;
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE, 0, NULL);
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ return BLOCKNAME;
+ if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1))
+ return TYPENAME;
+
+ if(sym)
+ {
+ switch(sym->class)
+ {
+ case LOC_STATIC:
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ case LOC_CONST:
+ case LOC_CONST_BYTES:
+ case LOC_OPTIMIZED_OUT:
+ return NAME;
+
+ case LOC_TYPEDEF:
+ return TYPENAME;
+
+ case LOC_BLOCK:
+ return BLOCKNAME;
+
+ case LOC_UNDEF:
+ error("internal: Undefined class in m2lex()");
+
+ case LOC_LABEL:
+ error("internal: Unforseen case in m2lex()");
+ }
+ }
+ else
+ {
+ /* Built-in BOOLEAN type. This is sort of a hack. */
+ if(STREQN(tokstart,"TRUE",4))
+ {
+ yylval.ulval = 1;
+ return M2_TRUE;
+ }
+ else if(STREQN(tokstart,"FALSE",5))
+ {
+ yylval.ulval = 0;
+ return M2_FALSE;
+ }
+ }
+
+ /* Must be another type of name... */
+ return NAME;
+ }
+}
+
+#if 0 /* Unused */
+static char *
+make_qualname(mod,ident)
+ char *mod, *ident;
+{
+ char *new = malloc(strlen(mod)+strlen(ident)+2);
+
+ strcpy(new,mod);
+ strcat(new,".");
+ strcat(new,ident);
+ return new;
+}
+#endif /* 0 */
+
+void
+yyerror(msg)
+ char *msg; /* unused */
+{
+ printf("Parsing: %s\n",lexptr);
+ if (yychar < 256)
+ error("Invalid syntax in expression near character '%c'.",yychar);
+ else
+ error("Invalid syntax in expression");
+}
+
diff --git a/gnu/usr.bin/gdb/gdb/m2-lang.c b/gnu/usr.bin/gdb/gdb/m2-lang.c
new file mode 100644
index 000000000000..0b678fd9c3c1
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/m2-lang.c
@@ -0,0 +1,457 @@
+/* Modula 2 language support routines for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "m2-lang.h"
+
+/* Print the character C on STREAM as part of the contents of a literal
+ string whose delimiter is QUOTER. Note that that format for printing
+ characters and strings is language specific.
+ FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true Modula version.
+ */
+
+static void
+emit_char (c, stream, quoter)
+ register int c;
+ FILE *stream;
+ int quoter;
+{
+
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (c == '\\' || c == quoter)
+ {
+ fputs_filtered ("\\", stream);
+ }
+ fprintf_filtered (stream, "%c", c);
+ }
+ else
+ {
+ 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;
+ }
+ }
+}
+
+/* FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true Modula version. */
+
+static void
+m2_printchar (c, stream)
+ int c;
+ FILE *stream;
+{
+ fputs_filtered ("'", stream);
+ emit_char (c, stream, '\'');
+ fputs_filtered ("'", stream);
+}
+
+/* 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.
+ FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true Modula version. */
+
+static void
+m2_printstr (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;
+ extern int repeat_count_threshold;
+ extern int print_max;
+
+ 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;
+ }
+ m2_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;
+ }
+ emit_char (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);
+}
+
+/* FIXME: This is a copy of c_create_fundamental_type(), before
+ all the non-C types were stripped from it. Needs to be fixed
+ by an experienced Modula programmer. */
+
+static struct type *
+m2_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type *type = NULL;
+
+ switch (typeid)
+ {
+ default:
+ /* FIXME: For now, if we are asked to produce a type not in this
+ language, create the equivalent of a C integer type with the
+ name "<?type?>". When all the dust settles from the type
+ reconstruction work, this should probably become an error. */
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "<?type?>", objfile);
+ warning ("internal error: no Modula fundamental type %d", typeid);
+ break;
+ case FT_VOID:
+ type = init_type (TYPE_CODE_VOID,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "void", objfile);
+ break;
+ case FT_BOOLEAN:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "boolean", objfile);
+ break;
+ case FT_STRING:
+ type = init_type (TYPE_CODE_STRING,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "string", objfile);
+ break;
+ case FT_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "char", objfile);
+ break;
+ case FT_SIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "signed char", objfile);
+ break;
+ case FT_UNSIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
+ break;
+ case FT_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "short", objfile);
+ break;
+ case FT_SIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "short", objfile); /* FIXME-fnf */
+ break;
+ case FT_UNSIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
+ break;
+ case FT_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "int", objfile);
+ break;
+ case FT_SIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "int", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
+ break;
+ case FT_FIXED_DECIMAL:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "fixed decimal", objfile);
+ break;
+ case FT_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long", objfile);
+ break;
+ case FT_SIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "long", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
+ break;
+ case FT_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long long", objfile);
+ break;
+ case FT_SIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED, "signed long long", objfile);
+ break;
+ case FT_UNSIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
+ break;
+ case FT_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "float", objfile);
+ break;
+ case FT_DBL_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "double", objfile);
+ break;
+ case FT_FLOAT_DECIMAL:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "floating decimal", objfile);
+ break;
+ case FT_EXT_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "long double", objfile);
+ break;
+ case FT_COMPLEX:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0, "complex", objfile);
+ break;
+ case FT_DBL_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0, "double complex", objfile);
+ break;
+ case FT_EXT_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0, "long double complex", objfile);
+ break;
+ }
+ return (type);
+}
+
+
+/* Table of operators and their precedences for printing expressions. */
+
+static const struct op_print m2_op_print_tab[] = {
+ {"+", BINOP_ADD, PREC_ADD, 0},
+ {"+", UNOP_PLUS, PREC_PREFIX, 0},
+ {"-", BINOP_SUB, PREC_ADD, 0},
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {"*", BINOP_MUL, PREC_MUL, 0},
+ {"/", BINOP_DIV, PREC_MUL, 0},
+ {"DIV", BINOP_INTDIV, PREC_MUL, 0},
+ {"MOD", BINOP_REM, PREC_MUL, 0},
+ {":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+ {"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+ {"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 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},
+ {"^", UNOP_IND, PREC_PREFIX, 0},
+ {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+ {NULL, 0, 0, 0}
+};
+
+/* The built-in types of Modula-2. */
+
+struct type *builtin_type_m2_char;
+struct type *builtin_type_m2_int;
+struct type *builtin_type_m2_card;
+struct type *builtin_type_m2_real;
+struct type *builtin_type_m2_bool;
+
+struct type ** const (m2_builtin_types[]) =
+{
+ &builtin_type_m2_char,
+ &builtin_type_m2_int,
+ &builtin_type_m2_card,
+ &builtin_type_m2_real,
+ &builtin_type_m2_bool,
+ 0
+};
+
+const struct language_defn m2_language_defn = {
+ "modula-2",
+ language_m2,
+ m2_builtin_types,
+ range_check_on,
+ type_check_on,
+ m2_parse, /* parser */
+ m2_error, /* parser error function */
+ m2_printchar, /* Print character constant */
+ m2_printstr, /* function to print string constant */
+ m2_create_fundamental_type, /* Create fundamental type in this language */
+ m2_print_type, /* Print a type using appropriate syntax */
+ m2_val_print, /* Print a value using appropriate syntax */
+ &builtin_type_m2_int, /* longest signed integral type */
+ &builtin_type_m2_card, /* longest unsigned integral type */
+ &builtin_type_m2_real, /* longest floating point type */
+ {"", "", "", ""}, /* Binary format info */
+ {"%loB", "", "o", "B"}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0%lXH", "0", "X", "H"}, /* Hex format info */
+ m2_op_print_tab, /* expression operators for printing */
+ LANG_MAGIC
+};
+
+/* Initialization for Modula-2 */
+
+void
+_initialize_m2_language ()
+{
+ /* Modula-2 "pervasive" types. NOTE: these can be redefined!!! */
+ builtin_type_m2_int =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "INTEGER", (struct objfile *) NULL);
+ builtin_type_m2_card =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "CARDINAL", (struct objfile *) NULL);
+ builtin_type_m2_real =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "REAL", (struct objfile *) NULL);
+ builtin_type_m2_char =
+ init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "CHAR", (struct objfile *) NULL);
+ builtin_type_m2_bool =
+ init_type (TYPE_CODE_BOOL, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "BOOLEAN", (struct objfile *) NULL);
+
+ TYPE_NFIELDS(builtin_type_m2_bool) = 2;
+ TYPE_FIELDS(builtin_type_m2_bool) =
+ (struct field *) xmalloc (sizeof (struct field) * 2);
+ TYPE_FIELD_BITPOS(builtin_type_m2_bool,0) = 0;
+ TYPE_FIELD_NAME(builtin_type_m2_bool,0) = (char *)xmalloc(6);
+ strcpy(TYPE_FIELD_NAME(builtin_type_m2_bool,0),"FALSE");
+ TYPE_FIELD_BITPOS(builtin_type_m2_bool,1) = 1;
+ TYPE_FIELD_NAME(builtin_type_m2_bool,1) = (char *)xmalloc(5);
+ strcpy(TYPE_FIELD_NAME(builtin_type_m2_bool,1),"TRUE");
+
+ add_language (&m2_language_defn);
+}
diff --git a/gnu/usr.bin/gdb/gdb/m2-lang.h b/gnu/usr.bin/gdb/gdb/m2-lang.h
new file mode 100644
index 000000000000..4bc57f5c2943
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/m2-lang.h
@@ -0,0 +1,31 @@
+/* Modula 2 language support definitions for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+extern int
+m2_parse PARAMS ((void)); /* Defined in m2-exp.y */
+
+extern void
+m2_error PARAMS ((char *)); /* Defined in m2-exp.y */
+
+extern void /* Defined in m2-typeprint.c */
+m2_print_type PARAMS ((struct type *, char *, FILE *, int, int));
+
+extern int
+m2_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int,
+ int, enum val_prettyprint));
diff --git a/gnu/usr.bin/gdb/gdb/m2-typeprint.c b/gnu/usr.bin/gdb/gdb/m2-typeprint.c
new file mode 100644
index 000000000000..ef66a80a8b90
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/m2-typeprint.c
@@ -0,0 +1,49 @@
+/* Support for printing Modula 2 types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "demangle.h"
+#include "m2-lang.h"
+
+#include <string.h>
+#include <errno.h>
+
+void
+m2_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ FILE *stream;
+ int show;
+ int level;
+{
+ extern void c_print_type PARAMS ((struct type *, char *, FILE *, int, int));
+
+ c_print_type (type, varstring, stream, show, level); /* FIXME */
+}
diff --git a/gnu/usr.bin/gdb/gdb/m2-valprint.c b/gnu/usr.bin/gdb/gdb/m2-valprint.c
new file mode 100644
index 000000000000..fc17ea50c9a3
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/m2-valprint.c
@@ -0,0 +1,45 @@
+/* Support for printing Modula 2 values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "valprint.h"
+
+/* FIXME: For now, just explicitly declare c_val_print and use it instead */
+
+int
+m2_val_print (type, valaddr, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ extern int
+ c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int,
+ int, enum val_prettyprint));
+ return (c_val_print (type, valaddr, address, stream, format, deref_ref,
+ recurse, pretty));
+}
diff --git a/gnu/usr.bin/gdb/gdb/main.c b/gnu/usr.bin/gdb/gdb/main.c
new file mode 100644
index 000000000000..deaf6240ef98
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/main.c
@@ -0,0 +1,2799 @@
+/* Top level `main' program for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "call-cmds.h"
+#include "symtab.h"
+#include "inferior.h"
+#include "signals.h"
+#include "target.h"
+#include "breakpoint.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "language.h"
+#include "terminal.h" /* For job_control. */
+
+#include "getopt.h"
+
+/* readline include files */
+#include "readline.h"
+#include "history.h"
+
+/* readline defines this. */
+#undef savestring
+
+#ifdef USG
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include <string.h>
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#include <setjmp.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#ifdef SET_STACK_LIMIT_HUGE
+#include <sys/time.h>
+#include <sys/resource.h>
+
+int original_stack_limit;
+#endif
+
+/* Prototypes for local functions */
+
+static char *
+symbol_completion_function PARAMS ((char *, int));
+
+static void
+command_loop PARAMS ((void));
+
+static void
+command_loop_marker PARAMS ((int));
+
+static void
+print_gdb_version PARAMS ((FILE *));
+
+static void
+quit_command PARAMS ((char *, int));
+
+static void
+init_main PARAMS ((void));
+
+static void
+init_history PARAMS ((void));
+
+static void
+init_cmd_lists PARAMS ((void));
+
+static void
+float_handler PARAMS ((int));
+
+static void
+source_command PARAMS ((char *, int));
+
+static void cd_command PARAMS ((char *, int));
+
+static void
+print_gnu_advertisement PARAMS ((void));
+
+static void
+init_signals PARAMS ((void));
+
+static void
+read_command_file PARAMS ((FILE *));
+
+static void
+set_verbose PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+show_history PARAMS ((char *, int));
+
+static void
+set_history PARAMS ((char *, int));
+
+static void
+set_history_size_command PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+show_commands PARAMS ((char *, int));
+
+static void
+echo_command PARAMS ((char *, int));
+
+static void
+pwd_command PARAMS ((char *, int));
+
+static void
+show_version PARAMS ((char *, int));
+
+static void
+document_command PARAMS ((char *, int));
+
+static void
+define_command PARAMS ((char *, int));
+
+static void
+validate_comname PARAMS ((char *));
+
+static void
+help_command PARAMS ((char *, int));
+
+static void
+show_command PARAMS ((char *, int));
+
+static void
+info_command PARAMS ((char *, int));
+
+static void
+do_nothing PARAMS ((int));
+
+static int
+quit_cover PARAMS ((char *));
+
+static void
+disconnect PARAMS ((int));
+
+static void
+source_cleanup PARAMS ((FILE *));
+
+/* 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
+static char gdbinit[] = GDBINIT_FILENAME;
+static int inhibit_gdbinit = 0;
+
+#define ALL_CLEANUPS ((struct cleanup *)0)
+
+/* Version number of GDB, as a string. */
+
+extern char *version;
+
+/* Canonical host name as a string. */
+
+extern char *host_canonical;
+
+/* Canonical target name as a string. */
+
+extern char *target_canonical;
+
+/* Message to be printed before the error message, when an error occurs. */
+
+extern char *error_pre_print;
+
+/* Message to be printed before the warning message, when a warning occurs. */
+
+extern char *warning_pre_print;
+
+extern char lang_frame_mismatch_warn[]; /* language.c */
+
+/* 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 unset subcommands */
+
+struct cmd_list_element *unsetlist;
+
+/* 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;
+
+/* Chain containing all defined maintenance subcommands. */
+
+#if MAINTENANCE_CMDS
+struct cmd_list_element *maintenancelist;
+#endif
+
+/* Chain containing all defined "maintenance info" subcommands. */
+
+#if MAINTENANCE_CMDS
+struct cmd_list_element *maintenanceinfolist;
+#endif
+
+/* Chain containing all defined "maintenance print" subcommands. */
+
+#if MAINTENANCE_CMDS
+struct cmd_list_element *maintenanceprintlist;
+#endif
+
+struct cmd_list_element *setprintlist;
+
+struct cmd_list_element *showprintlist;
+
+struct cmd_list_element *setchecklist;
+
+struct cmd_list_element *showchecklist;
+
+/* stdio stream that command input is being read from. Set to stdin normally.
+ Set by source_command to the file we are sourcing. Set to NULL if we are
+ executing a user-defined command. */
+
+FILE *instream;
+
+/* Current working directory. */
+
+char *current_directory;
+
+/* The directory name is actually stored here (usually). */
+static char dirbuf[1024];
+
+/* Function to call before reading a command, if nonzero.
+ The function receives two args: an input stream,
+ and a prompt string. */
+
+void (*window_hook) PARAMS ((FILE *, char *));
+
+extern int mapped_symbol_files;
+extern int readnow_symbol_files;
+
+int epoch_interface;
+int xgdb_verbose;
+
+/* 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 -1, so targets can choose their own defaults. */
+
+int baud_rate = -1;
+
+/* Non-zero tells remote* modules to output debugging info. */
+
+int remote_debug = 0;
+
+/* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */
+
+#ifndef STOP_SIGNAL
+#ifdef SIGTSTP
+#define STOP_SIGNAL SIGTSTP
+static void stop_sig PARAMS ((int));
+#endif
+#endif
+
+/* Some System V have job control but not sigsetmask(). */
+#if !defined (HAVE_SIGSETMASK)
+#define HAVE_SIGSETMASK !defined (USG)
+#endif
+
+#if 0 == (HAVE_SIGSETMASK)
+#define sigsetmask(n)
+#endif
+
+/* Where to go for return_to_top_level (RETURN_ERROR). */
+static jmp_buf error_return;
+/* Where to go for return_to_top_level (RETURN_QUIT). */
+static jmp_buf quit_return;
+
+/* Temporary variable for SET_TOP_LEVEL. */
+static int top_level_val;
+
+/* Do a setjmp on error_return and quit_return. catch_errors is
+ generally a cleaner way to do this, but main() would look pretty
+ ugly if it had to use catch_errors each time. */
+
+#define SET_TOP_LEVEL() \
+ (((top_level_val = setjmp (error_return)) \
+ ? (PTR) 0 : (PTR) memcpy (quit_return, error_return, sizeof (jmp_buf))) \
+ , top_level_val)
+
+/* Return for reason REASON. This generally gets back to the command
+ loop, but can be caught via catch_errors. */
+
+NORETURN void
+return_to_top_level (reason)
+ enum return_reason reason;
+{
+ quit_flag = 0;
+ immediate_quit = 0;
+
+ /* Perhaps it would be cleaner to do this via the cleanup chain (not sure
+ I can think of a reason why that is vital, though). */
+ bpstat_clear_actions(stop_bpstat); /* Clear queued breakpoint commands */
+
+ disable_current_display ();
+ do_cleanups (ALL_CLEANUPS);
+ (NORETURN void) longjmp
+ (reason == RETURN_ERROR ? error_return : quit_return, 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,
+ print ERRSTRING, print the specific error message, then return
+ zero.
+
+ Must not be called with immediate_quit in effect (bad things might
+ happen, say we got a signal in the middle of a memcpy to quit_return).
+ This is an OK restriction; with very few exceptions immediate_quit can
+ be replaced by judicious use of QUIT.
+
+ MASK specifies what to catch; it is normally set to
+ RETURN_MASK_ALL, if for no other reason than that the code which
+ calls catch_errors might not be set up to deal with a quit which
+ isn't caught. But if the code can deal with it, it generally
+ should be RETURN_MASK_ERROR, unless for some reason it is more
+ useful to abort only the portion of the operation inside the
+ catch_errors. Note that quit should return to the command line
+ fairly quickly, even if some further processing is being done. */
+
+int
+catch_errors (func, args, errstring, mask)
+ int (*func) PARAMS ((char *));
+ PTR args;
+ char *errstring;
+ return_mask mask;
+{
+ jmp_buf saved_error;
+ jmp_buf saved_quit;
+ jmp_buf tmp_jmp;
+ int val;
+ struct cleanup *saved_cleanup_chain;
+ char *saved_error_pre_print;
+
+ saved_cleanup_chain = save_cleanups ();
+ saved_error_pre_print = error_pre_print;
+
+ if (mask & RETURN_MASK_ERROR)
+ memcpy ((char *)saved_error, (char *)error_return, sizeof (jmp_buf));
+ if (mask & RETURN_MASK_QUIT)
+ memcpy (saved_quit, quit_return, sizeof (jmp_buf));
+ error_pre_print = errstring;
+
+ if (setjmp (tmp_jmp) == 0)
+ {
+ if (mask & RETURN_MASK_ERROR)
+ memcpy (error_return, tmp_jmp, sizeof (jmp_buf));
+ if (mask & RETURN_MASK_QUIT)
+ memcpy (quit_return, tmp_jmp, sizeof (jmp_buf));
+ val = (*func) (args);
+ }
+ else
+ val = 0;
+
+ restore_cleanups (saved_cleanup_chain);
+
+ error_pre_print = saved_error_pre_print;
+ if (mask & RETURN_MASK_ERROR)
+ memcpy (error_return, saved_error, sizeof (jmp_buf));
+ if (mask & RETURN_MASK_QUIT)
+ memcpy (quit_return, saved_quit, sizeof (jmp_buf));
+ return val;
+}
+
+/* Handler for SIGHUP. */
+
+static void
+disconnect (signo)
+int signo;
+{
+ catch_errors (quit_cover, NULL,
+ "Could not kill the program being debugged", RETURN_MASK_ALL);
+ signal (SIGHUP, SIG_DFL);
+ kill (getpid (), SIGHUP);
+}
+
+/* Just a little helper function for disconnect(). */
+
+static int
+quit_cover (s)
+char *s;
+{
+ caution = 0; /* Throw caution to the wind -- we're exiting.
+ This prevents asking the user dumb questions. */
+ quit_command((char *)0, 0);
+ return 0;
+}
+
+/* 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);
+}
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int count;
+ 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;
+
+ /* These are static so that we can take their address in an initializer. */
+ static int print_help;
+ static int print_version;
+
+ /* 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;
+
+ struct stat homebuf, cwdbuf;
+ char *homedir, *homeinit;
+
+ register int i;
+
+ /* This needs to happen before the first use of malloc. */
+ init_malloc ((PTR) NULL);
+
+#if defined (ALIGN_STACK_ON_STARTUP)
+ i = (int) &count & 0x3;
+ if (i != 0)
+ alloca (4 - i);
+#endif
+
+ /* If error() is called from initialization code, just exit */
+ if (SET_TOP_LEVEL ()) {
+ exit(1);
+ }
+
+ 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;
+
+ getcwd (dirbuf, sizeof (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;
+ /* 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[] =
+ {
+ {"readnow", no_argument, &readnow_symbol_files, 1},
+ {"r", no_argument, &readnow_symbol_files, 1},
+ {"mapped", no_argument, &mapped_symbol_files, 1},
+ {"m", no_argument, &mapped_symbol_files, 1},
+ {"quiet", no_argument, &quiet, 1},
+ {"q", no_argument, &quiet, 1},
+ {"silent", no_argument, &quiet, 1},
+ {"nx", no_argument, &inhibit_gdbinit, 1},
+ {"n", no_argument, &inhibit_gdbinit, 1},
+ {"batch", no_argument, &batch, 1},
+ {"epoch", no_argument, &epoch_interface, 1},
+ {"fullname", no_argument, &frame_file_full_name, 1},
+ {"f", no_argument, &frame_file_full_name, 1},
+ {"help", no_argument, &print_help, 1},
+ {"se", required_argument, 0, 10},
+ {"symbols", required_argument, 0, 's'},
+ {"s", required_argument, 0, 's'},
+ {"exec", required_argument, 0, 'e'},
+ {"e", required_argument, 0, 'e'},
+ {"core", required_argument, 0, 'c'},
+ {"c", required_argument, 0, 'c'},
+ {"command", required_argument, 0, 'x'},
+ {"version", no_argument, &print_version, 1},
+ {"x", required_argument, 0, 'x'},
+ {"directory", required_argument, 0, 'd'},
+ {"cd", required_argument, 0, 11},
+ {"tty", required_argument, 0, 't'},
+ {"baud", required_argument, 0, 'b'},
+ {"b", required_argument, 0, 'b'},
+/* Allow machine descriptions to add more options... */
+#ifdef ADDITIONAL_OPTIONS
+ ADDITIONAL_OPTIONS
+#endif
+ {0, no_argument, 0, 0},
+ };
+
+ while (1)
+ {
+ int option_index;
+
+ 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':
+ {
+ int i;
+ char *p;
+
+ i = strtol (optarg, &p, 0);
+ if (i == 0 && p == optarg)
+ warning ("Could not set baud rate to `%s'.\n", optarg);
+ else
+ baud_rate = i;
+ }
+ 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);
+ }
+ }
+
+ /* 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 */
+
+ init_cmd_lists (); /* This needs to be done first */
+ initialize_all_files ();
+ init_main (); /* But that omits this file! Do it now */
+ init_signals ();
+
+ /* Do these (and anything which might call wrap_here or *_filtered)
+ after initialize_all_files. */
+ if (print_version)
+ {
+ print_gdb_version (stdout);
+ wrap_here ("");
+ printf_filtered ("\n");
+ exit (0);
+ }
+
+ if (print_help)
+ {
+ /* --version is intentionally not documented here, because we
+ are printing the version here, and the help is long enough
+ already. */
+
+ print_gdb_version (stdout);
+ /* Make sure the output gets printed. */
+ wrap_here ("");
+ printf_filtered ("\n");
+
+ /* But don't use *_filtered here. We don't want to prompt for continue
+ no matter how small the screen or how much we're going to print. */
+ fputs ("\
+This is the GNU debugger. Usage:\n\
+ gdb [options] [executable-file [core-file or process-id]]\n\
+Options:\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\
+ --mapped Use mapped symbol files if supported on this system.\n\
+ --readnow Fully read symbol files on first access.\n\
+", stdout);
+#ifdef ADDITIONAL_OPTION_HELP
+ fputs (ADDITIONAL_OPTION_HELP, stdout);
+#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", stdout);
+ exit (0);
+ }
+
+ if (!quiet)
+ {
+ /* Print all the junk at the top, with trailing "..." if we are about
+ to read a symbol file (possibly slowly). */
+ print_gnu_advertisement ();
+ print_gdb_version (stdout);
+ if (symarg)
+ printf_filtered ("..");
+ wrap_here("");
+ fflush (stdout); /* Force to screen during slow operations */
+ }
+
+ error_pre_print = "\n\n";
+ /* We may get more than one warning, don't double space all of them... */
+ warning_pre_print = "\nwarning: ";
+
+ /* We need a default language for parsing expressions, so simple things like
+ "set width 0" won't fail if no language is explicitly set in a config file
+ or implicitly set by reading an executable during startup. */
+ set_language (language_c);
+ expected_language = current_language; /* don't warn about the change. */
+
+ /* Read and execute $HOME/.gdbinit file, if it exists. This is done
+ *before* all the command line arguments are processed; it sets
+ global parameters, which are independent of what file you are
+ debugging or what directory you are in. */
+ 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 (!SET_TOP_LEVEL ())
+ source_command (homeinit, 0);
+ }
+ do_cleanups (ALL_CLEANUPS);
+
+ /* 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). */
+
+ memset (&homebuf, 0, sizeof (struct stat));
+ memset (&cwdbuf, 0, sizeof (struct stat));
+
+ stat (homeinit, &homebuf);
+ stat (gdbinit, &cwdbuf); /* We'll only need this if
+ homedir was set. */
+ }
+
+ /* Now perform all the actions indicated by the arguments. */
+ if (cdarg != NULL)
+ {
+ if (!SET_TOP_LEVEL ())
+ {
+ cd_command (cdarg, 0);
+ init_source_path ();
+ }
+ }
+ do_cleanups (ALL_CLEANUPS);
+
+ for (i = 0; i < ndir; i++)
+ if (!SET_TOP_LEVEL ())
+ directory_command (dirarg[i], 0);
+ free ((PTR)dirarg);
+ do_cleanups (ALL_CLEANUPS);
+
+ if (execarg != NULL
+ && symarg != NULL
+ && STREQ (execarg, symarg))
+ {
+ /* The exec file and the symbol-file are the same. If we can't open
+ it, better only print one error message. */
+ if (!SET_TOP_LEVEL ())
+ {
+ exec_file_command (execarg, !batch);
+ symbol_file_command (symarg, 0);
+ }
+ }
+ else
+ {
+ if (execarg != NULL)
+ if (!SET_TOP_LEVEL ())
+ exec_file_command (execarg, !batch);
+ if (symarg != NULL)
+ if (!SET_TOP_LEVEL ())
+ symbol_file_command (symarg, 0);
+ }
+ do_cleanups (ALL_CLEANUPS);
+
+ /* After the symbol file has been read, print a newline to get us
+ beyond the copyright line... But errors should still set off
+ the error message with a (single) blank line. */
+ if (!quiet)
+ printf_filtered ("\n");
+ error_pre_print = "\n";
+ warning_pre_print = "\nwarning: ";
+
+ if (corearg != NULL)
+ if (!SET_TOP_LEVEL ())
+ core_file_command (corearg, !batch);
+ else if (isdigit (corearg[0]) && !SET_TOP_LEVEL ())
+ attach_command (corearg, !batch);
+ do_cleanups (ALL_CLEANUPS);
+
+ if (ttyarg != NULL)
+ if (!SET_TOP_LEVEL ())
+ tty_command (ttyarg, !batch);
+ do_cleanups (ALL_CLEANUPS);
+
+#ifdef ADDITIONAL_OPTION_HANDLER
+ ADDITIONAL_OPTION_HANDLER;
+#endif
+
+ /* Error messages should no longer be distinguished with extra output. */
+ error_pre_print = 0;
+ warning_pre_print = "warning: ";
+
+ /* Read the .gdbinit file in the current directory, *if* it isn't
+ the same as the $HOME/.gdbinit file (it should exist, also). */
+
+ if (!homedir
+ || memcmp ((char *) &homebuf, (char *) &cwdbuf, sizeof (struct stat)))
+ if (!inhibit_gdbinit && access (gdbinit, R_OK) == 0)
+ {
+ if (!SET_TOP_LEVEL ())
+ source_command (gdbinit, 0);
+ }
+ do_cleanups (ALL_CLEANUPS);
+
+ for (i = 0; i < ncmd; i++)
+ {
+ if (!SET_TOP_LEVEL ())
+ {
+ if (cmdarg[i][0] == '-' && cmdarg[i][1] == '\0')
+ read_command_file (stdin);
+ else
+ source_command (cmdarg[i], !batch);
+ do_cleanups (ALL_CLEANUPS);
+ }
+ }
+ free ((PTR)cmdarg);
+
+ /* Read in the old history after all the command files have been read. */
+ init_history();
+
+ 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 (!SET_TOP_LEVEL ())
+ {
+ do_cleanups (ALL_CLEANUPS); /* Do complete cleanup */
+ command_loop ();
+ quit_command ((char *)0, instream == stdin);
+ }
+ }
+ /* No exit -- exit is through quit_command. */
+}
+
+void
+execute_user_command (c, args)
+ struct cmd_list_element *c;
+ char *args;
+{
+ register struct command_line *cmdlines;
+ struct cleanup *old_chain;
+
+ if (args)
+ 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);
+}
+
+/* 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 enum language flang;
+ static int warned = 0;
+
+ 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 this command has been hooked, run the hook first. */
+ if (c->hook)
+ execute_user_command (c->hook, (char *)0);
+
+ if (c->class == class_user)
+ execute_user_command (c, arg);
+ else if (c->type == set_cmd || c->type == show_cmd)
+ do_setshow_command (arg, from_tty & caution, c);
+ else if (c->function.cfunc == NO_FUNCTION)
+ error ("That is not a command, just a help topic.");
+ else
+ (*c->function.cfunc) (arg, from_tty & caution);
+ }
+
+ /* Tell the user if the language has changed (except first time). */
+ if (current_language != expected_language)
+ {
+ if (language_mode == language_mode_auto) {
+ language_info (1); /* Print what changed. */
+ }
+ warned = 0;
+ }
+
+ /* Warn the user if the working language does not match the
+ language of the current frame. Only warn the user if we are
+ actually running the program, i.e. there is a stack. */
+ /* FIXME: This should be cacheing the frame and only running when
+ the frame changes. */
+ if (target_has_stack)
+ {
+ flang = get_frame_language ();
+ if (!warned
+ && flang != language_unknown
+ && flang != current_language->la_language)
+ {
+ printf_filtered ("%s\n", lang_frame_mismatch_warn);
+ warned = 1;
+ }
+ }
+}
+
+/* ARGSUSED */
+static void
+command_loop_marker (foo)
+ int foo;
+{
+}
+
+/* Read commands from `instream' and execute them
+ until end of file or error reading instream. */
+static 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 (command_loop_marker, 0);
+ command = command_line_input (instream == stdin ? prompt : (char *) NULL,
+ 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);
+ }
+}
+
+/* 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;
+}
+
+/* Read a line from the stream "instream" without command line editing.
+
+ It prints PRROMPT once at the start.
+ Action is compatible with "readline", e.g. space for the result is
+ malloc'd and should be freed by the caller.
+
+ A NULL return means end of file. */
+char *
+gdb_readline (prrompt)
+ char *prrompt;
+{
+ int c;
+ char *result;
+ int input_index = 0;
+ int result_size = 80;
+
+ if (prrompt)
+ {
+ /* Don't use a _filtered function here. It causes the assumed
+ character position to be off, since the newline we read from
+ the user is not accounted for. */
+ fputs (prrompt, stdout);
+ fflush (stdout);
+ }
+
+ 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)
+ {
+ if (input_index > 0)
+ /* The last line does not end with a newline. Return it, and
+ if we are called again fgetc will still return EOF and
+ we'll return NULL then. */
+ break;
+ free (result);
+ return NULL;
+ }
+
+ if (c == '\n')
+ break;
+
+ result[input_index++] = c;
+ while (input_index >= result_size)
+ {
+ result_size *= 2;
+ result = (char *) xrealloc (result, result_size);
+ }
+ }
+
+ result[input_index++] = '\0';
+ return result;
+}
+
+/* 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;
+
+/* readline uses the word breaks for two things:
+ (1) In figuring out where to point the TEXT parameter to the
+ rl_completion_entry_function. Since we don't use TEXT for much,
+ it doesn't matter a lot what the word breaks are for this purpose, but
+ it does affect how much stuff M-? lists.
+ (2) If one of the matches contains a word break character, readline
+ will quote it. That's why we switch between
+ gdb_completer_word_break_characters and
+ gdb_completer_command_word_break_characters. I'm not sure when
+ we need this behavior (perhaps for funky characters in C++ symbols?). */
+
+/* Variables which are necessary for fancy command line editing. */
+char *gdb_completer_word_break_characters =
+ " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,-";
+
+/* When completing on command names, we remove '-' from the list of
+ word break characters, since we use it in command names. If the
+ readline library sees one in any of the current completion strings,
+ it thinks that the string needs to be quoted and automatically supplies
+ a leading quote. */
+char *gdb_completer_command_word_break_characters =
+ " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,";
+
+/* Characters that can be used to quote completion strings. Note that we
+ can't include '"' because the gdb C parser treats such quoted sequences
+ as strings. */
+char *gdb_completer_quote_characters =
+ "'";
+
+/* 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, prefix)
+ char *text;
+ char *prefix;
+{
+ return NULL;
+}
+
+/* Complete on filenames. */
+char **
+filename_completer (text, word)
+ char *text;
+ char *word;
+{
+ /* From readline. */
+ extern char *filename_completion_function ();
+ int subsequent_name;
+ char **return_val;
+ int return_val_used;
+ int return_val_alloced;
+
+ return_val_used = 0;
+ /* Small for testing. */
+ return_val_alloced = 1;
+ return_val = (char **) xmalloc (return_val_alloced * sizeof (char *));
+
+ subsequent_name = 0;
+ while (1)
+ {
+ char *p;
+ p = filename_completion_function (text, subsequent_name);
+ if (return_val_used >= return_val_alloced)
+ {
+ return_val_alloced *= 2;
+ return_val =
+ (char **) xrealloc (return_val,
+ return_val_alloced * sizeof (char *));
+ }
+ if (p == NULL)
+ {
+ return_val[return_val_used++] = p;
+ break;
+ }
+ /* Like emacs, don't complete on old versions. Especially useful
+ in the "source" command. */
+ if (p[strlen (p) - 1] == '~')
+ continue;
+
+ {
+ char *q;
+ if (word == text)
+ /* Return exactly p. */
+ return_val[return_val_used++] = p;
+ else if (word > text)
+ {
+ /* Return some portion of p. */
+ q = xmalloc (strlen (p) + 5);
+ strcpy (q, p + (word - text));
+ return_val[return_val_used++] = q;
+ free (p);
+ }
+ else
+ {
+ /* Return some of TEXT plus p. */
+ q = xmalloc (strlen (p) + (text - word) + 5);
+ strncpy (q, word, text - word);
+ q[text - word] = '\0';
+ strcat (q, p);
+ return_val[return_val_used++] = q;
+ free (p);
+ }
+ }
+ subsequent_name = 1;
+ }
+#if 0
+ /* There is no way to do this just long enough to affect quote inserting
+ without also affecting the next completion. This should be fixed in
+ readline. FIXME. */
+ /* Insure that readline does the right thing
+ with respect to inserting quotes. */
+ rl_completer_word_break_characters = "";
+#endif
+ return return_val;
+}
+
+/* Here are some useful test cases for completion. FIXME: These should
+ be put in the test suite. They should be tested with both M-? and TAB.
+
+ "show output-" "radix"
+ "show output" "-radix"
+ "p" ambiguous (commands starting with p--path, print, printf, etc.)
+ "p " ambiguous (all symbols)
+ "info t foo" no completions
+ "info t " no completions
+ "info t" ambiguous ("info target", "info terminal", etc.)
+ "info ajksdlfk" no completions
+ "info ajksdlfk " no completions
+ "info" " "
+ "info " ambiguous (all info commands)
+ "p \"a" no completions (string constant)
+ "p 'a" ambiguous (all symbols starting with a)
+ "p b-a" ambiguous (all symbols starting with a)
+ "p b-" ambiguous (all symbols)
+ "file Make" "file" (word break hard to screw up here)
+ "file ../gdb.stabs/wi" "erd" (needs to not break word at slash)
+ */
+
+/* Generate completions one by one for the completer. Each time we are
+ called return another potential completion to the caller. The function
+ is misnamed; it just completes on commands or passes the buck to the
+ command's completer function; the stuff specific to symbol completion
+ is in make_symbol_completion_list.
+
+ TEXT is readline's idea of the "word" we are looking at; we don't really
+ like readline's ideas about word breaking so we ignore it.
+
+ MATCHES is the number of matches that have currently been collected from
+ calling this completion function. When zero, then we need to initialize,
+ otherwise the initialization has already taken place and we can just
+ return the next potential completion string.
+
+ Returns NULL if there are no more completions, else a pointer to a string
+ which is a possible completion.
+
+ 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. */
+
+static char *
+symbol_completion_function (text, matches)
+ char *text;
+ int matches;
+{
+ static char **list = (char **)NULL; /* Cache of completions */
+ static int index; /* Next cached completion */
+ char *output = NULL;
+ char *tmp_command, *p;
+ /* Pointer within tmp_command which corresponds to text. */
+ char *word;
+ struct cmd_list_element *c, *result_list;
+ extern char *rl_line_buffer;
+ extern int rl_point;
+
+ if (matches == 0)
+ {
+ /* The caller is beginning to accumulate a new set of completions, so
+ we need to find all of them now, and cache them for returning one at
+ a time on future calls. */
+
+ if (list)
+ {
+ /* Free the storage used by LIST, but not by the strings inside.
+ This is because rl_complete_internal () frees the strings. */
+ free ((PTR)list);
+ }
+ list = 0;
+ index = 0;
+
+ /* Choose the default set of word break characters to break completions.
+ If we later find out that we are doing completions on command strings
+ (as opposed to strings supplied by the individual command completer
+ functions, which can be any string) then we will switch to the
+ special word break set for command strings, which leaves out the
+ '-' character used in some commands. */
+
+ rl_completer_word_break_characters =
+ gdb_completer_word_break_characters;
+
+ /* 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';
+ /* Since text always contains some number of characters leading up
+ to rl_point, we can find the equivalent position in tmp_command
+ by subtracting that many characters from the end of tmp_command. */
+ word = tmp_command + rl_point - strlen (text);
+
+ 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)
+ {
+ /* It is an unrecognized command. So there are no
+ possible completions. */
+ list = NULL;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ char *q;
+
+ /* lookup_cmd_1 advances p up to the first ambiguous thing, but
+ doesn't advance over that thing itself. Do so now. */
+ q = p;
+ while (*q && (isalnum (*q) || *q == '-' || *q == '_'))
+ ++q;
+ if (q != tmp_command + rl_point)
+ {
+ /* There is something beyond the ambiguous
+ command, so there are no possible completions. For
+ example, "info t " or "info t foo" does not complete
+ to anything, because "info t" can be "info target" or
+ "info terminal". */
+ list = NULL;
+ }
+ else
+ {
+ /* We're trying to complete on the command which was ambiguous.
+ This we can deal with. */
+ if (result_list)
+ {
+ list = complete_on_cmdlist (*result_list->prefixlist, p,
+ word);
+ }
+ else
+ {
+ list = complete_on_cmdlist (cmdlist, p, word);
+ }
+ /* Insure that readline does the right thing with respect to
+ inserting quotes. */
+ rl_completer_word_break_characters =
+ gdb_completer_command_word_break_characters;
+ }
+ }
+ else
+ {
+ /* We've recognized a full command. */
+
+ if (p == tmp_command + rl_point)
+ {
+ /* There is no non-whitespace in the line beyond the command. */
+
+ if (p[-1] == ' ' || p[-1] == '\t')
+ {
+ /* The command is followed by whitespace; we need to complete
+ on whatever comes after command. */
+ if (c->prefixlist)
+ {
+ /* It is a prefix command; what comes after it is
+ a subcommand (e.g. "info "). */
+ list = complete_on_cmdlist (*c->prefixlist, p, word);
+
+ /* Insure that readline does the right thing
+ with respect to inserting quotes. */
+ rl_completer_word_break_characters =
+ gdb_completer_command_word_break_characters;
+ }
+ else
+ {
+ /* It is a normal command; what comes after it is
+ completed by the command's completer function. */
+ list = (*c->completer) (p, word);
+ }
+ }
+ else
+ {
+ /* The command is not followed by whitespace; we need to
+ complete on the command itself. e.g. "p" which is a
+ command itself but also can complete to "print", "ptype"
+ etc. */
+ char *q;
+
+ /* Find the command we are completing on. */
+ q = p;
+ while (q > tmp_command)
+ {
+ if (isalnum (q[-1]) || q[-1] == '-' || q[-1] == '_')
+ --q;
+ else
+ break;
+ }
+
+ list = complete_on_cmdlist (result_list, q, word);
+
+ /* Insure that readline does the right thing
+ with respect to inserting quotes. */
+ rl_completer_word_break_characters =
+ gdb_completer_command_word_break_characters;
+ }
+ }
+ else
+ {
+ /* There is non-whitespace beyond the command. */
+
+ if (c->prefixlist && !c->allow_unknown)
+ {
+ /* It is an unrecognized subcommand of a prefix command,
+ e.g. "info adsfkdj". */
+ list = NULL;
+ }
+ else
+ {
+ /* It is a normal command. */
+ list = (*c->completer) (p, word);
+ }
+ }
+ }
+ }
+
+ /* If we found a list of potential completions during initialization then
+ dole them out one at a time. The vector of completions is NULL
+ terminated, so after returning the last one, return NULL (and continue
+ to do so) each time we are called after that, until a new list is
+ available. */
+
+ if (list)
+ {
+ output = list[index];
+ if (output)
+ {
+ index++;
+ }
+ }
+
+#if 0
+ /* Can't do this because readline hasn't yet checked the word breaks
+ for figuring out whether to insert a quote. */
+ if (output == NULL)
+ /* Make sure the word break characters are set back to normal for the
+ next time that readline tries to complete something. */
+ rl_completer_word_break_characters =
+ gdb_completer_word_break_characters;
+#endif
+
+ return (output);
+}
+
+/* Skip over a possibly quoted word (as defined by the quote characters
+ and word break characters the completer uses). Returns pointer to the
+ location after the "word". */
+
+char *
+skip_quoted (str)
+ char *str;
+{
+ char quote_char = '\0';
+ char *scan;
+
+ for (scan = str; *scan != '\0'; scan++)
+ {
+ if (quote_char != '\0')
+ {
+ /* Ignore everything until the matching close quote char */
+ if (*scan == quote_char)
+ {
+ /* Found matching close quote. */
+ scan++;
+ break;
+ }
+ }
+ else if (strchr (gdb_completer_quote_characters, *scan))
+ {
+ /* Found start of a quoted string. */
+ quote_char = *scan;
+ }
+ else if (strchr (gdb_completer_word_break_characters, *scan))
+ {
+ break;
+ }
+ }
+ return (scan);
+}
+
+
+#ifdef STOP_SIGNAL
+static void
+stop_sig (signo)
+int signo;
+{
+#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 */
+
+/* Initialize signal handlers. */
+static void
+do_nothing (signo)
+int signo;
+{
+}
+
+static void
+init_signals ()
+{
+ 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 can affect the
+ GDB process as well as the inferior (the signal handling tables
+ might be in memory, shared between the two). 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);
+
+#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
+ signal (SIGWINCH, SIGWINCH_HANDLER);
+#endif
+}
+
+/* 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 unsigned 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
+ if (job_control)
+ signal (STOP_SIGNAL, stop_sig);
+#endif
+
+ while (1)
+ {
+ /* Reports are that some Sys V's don't flush stdout/err on reads
+ from stdin, when stdin/out are sockets rather than ttys. So we
+ have to do it ourselves, to make emacs-gdb and xxgdb work.
+ On other machines, doing this once per input should be a cheap nop. */
+ fflush (stdout);
+ fflush (stderr);
+
+ /* 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);
+
+ 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
+ if (job_control)
+ signal (STOP_SIGNAL, 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;
+}
+
+/* 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 ((char *) NULL, 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 ((PTR)l);
+ l = next;
+ }
+}
+
+/* Add an element to the list of info subcommands. */
+
+void
+add_info (name, fun, doc)
+ char *name;
+ void (*fun) PARAMS ((char *, int));
+ 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, "");
+}
+
+/* Add an element to the list of commands. */
+
+void
+add_com (name, class, fun, doc)
+ char *name;
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
+ 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);
+}
+
+/* ARGSUSED */
+static void
+help_command (command, from_tty)
+ char *command;
+ int from_tty; /* Ignored */
+{
+ help_cmd (command, stdout);
+}
+
+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 (!isalnum(*p) && *p != '-')
+ error ("Junk in argument list: \"%s\"", p);
+ p++;
+ }
+}
+
+/* This is just a placeholder in the command data structures. */
+static void
+user_defined_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+}
+
+static void
+define_command (comname, from_tty)
+ char *comname;
+ int from_tty;
+{
+ register struct command_line *cmds;
+ register struct cmd_list_element *c, *newc, *hookc = 0;
+ char *tem = comname;
+#define HOOK_STRING "hook-"
+#define HOOK_LEN 5
+
+ validate_comname (comname);
+
+ /* Look it up, and verify that we got an exact match. */
+ c = lookup_cmd (&tem, cmdlist, "", -1, 1);
+ if (c && !STREQ (comname, c->name))
+ c = 0;
+
+ 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, c->name))
+ error ("Command \"%s\" not redefined.", c->name);
+ }
+
+ /* If this new command is a hook, then mark the command which it
+ is hooking. Note that we allow hooking `help' commands, so that
+ we can hook the `stop' pseudo-command. */
+
+ if (!strncmp (comname, HOOK_STRING, HOOK_LEN))
+ {
+ /* Look up cmd it hooks, and verify that we got an exact match. */
+ tem = comname+HOOK_LEN;
+ hookc = lookup_cmd (&tem, cmdlist, "", -1, 0);
+ if (hookc && !STREQ (comname+HOOK_LEN, hookc->name))
+ hookc = 0;
+ if (!hookc)
+ {
+ warning ("Your new `%s' command does not hook any existing command.",
+ comname);
+ if (!query ("Proceed? ", (char *)0))
+ error ("Not confirmed.");
+ }
+ }
+
+ comname = savestring (comname, strlen (comname));
+
+ /* If the rest of the commands will be case insensitive, this one
+ should behave in the same manner. */
+ for (tem = comname; *tem; tem++)
+ if (isupper(*tem)) *tem = tolower(*tem);
+
+ if (from_tty)
+ {
+ printf ("Type commands for definition of \"%s\".\n\
+End with a line saying just \"end\".\n", comname);
+ fflush (stdout);
+ }
+
+ cmds = read_command_lines ();
+
+ if (c && c->class == class_user)
+ free_command_lines (&c->user_commands);
+
+ newc = add_cmd (comname, class_user, user_defined_command,
+ (c && c->class == class_user)
+ ? c->doc : savestring ("User-defined.", 13), &cmdlist);
+ newc->user_commands = cmds;
+
+ /* If this new command is a hook, then mark both commands as being
+ tied. */
+ if (hookc)
+ {
+ hookc->hook = newc; /* Target gets hooked. */
+ newc->hookee = hookc; /* We are marked as hooking target cmd. */
+ }
+}
+
+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);
+}
+
+static void
+print_gnu_advertisement()
+{
+ printf ("\
+GDB is free software and you are welcome to distribute copies of it\n\
+ under certain conditions; type \"show copying\" to see the conditions.\n\
+There is absolutely no warranty for GDB; type \"show warranty\" for details.\n\
+");
+}
+
+static void
+print_gdb_version (stream)
+ FILE *stream;
+{
+ fprintf_filtered (stream, "\
+GDB %s (%s", version, host_canonical);
+
+ if (strcmp(host_canonical, target_canonical))
+ fprintf_filtered (stream, " --target %s", target_canonical);
+
+ fprintf_filtered (stream, "), ");
+ wrap_here("");
+ fprintf_filtered (stream, "Copyright 1993 Free Software Foundation, Inc.");
+}
+
+/* ARGSUSED */
+static void
+show_version (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ immediate_quit++;
+ print_gnu_advertisement ();
+ print_gdb_version (stdout);
+ printf_filtered ("\n");
+ immediate_quit--;
+}
+
+/* xgdb calls this to reprint the usual GDB prompt. */
+
+void
+print_prompt ()
+{
+ printf ("%s", prompt);
+ fflush (stdout);
+}
+
+static void
+quit_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (inferior_pid != 0 && target_has_execution)
+ {
+ if (attach_flag)
+ {
+ if (query ("The program is running. Quit anyway (and detach it)? "))
+ target_detach (args, from_tty);
+ else
+ error ("Not confirmed.");
+ }
+ else
+ {
+ if (query ("The program is running. Quit anyway (and kill it)? "))
+ target_kill ();
+ 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);
+}
+
+/* Returns whether GDB is running on a terminal and whether the user
+ desires that questions be asked of them on that terminal. */
+
+int
+input_from_terminal_p ()
+{
+ return gdb_has_a_terminal () && (instream == stdin) & caution;
+}
+
+/* ARGSUSED */
+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);
+ getcwd (dirbuf, sizeof (dirbuf));
+
+ if (!STREQ (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;
+ /* Found something other than leading repetitions of "/..". */
+ int found_real_path;
+ char *p;
+
+ /* If the new directory is absolute, repeat is a no-op; if relative,
+ repeat might be useful but is more likely to be a mistake. */
+ dont_repeat ();
+
+ if (dir == 0)
+ error_no_arg ("new working directory");
+
+ dir = tilde_expand (dir);
+ make_cleanup (free, dir);
+
+ if (chdir (dir) < 0)
+ perror_with_name (dir);
+
+ len = strlen (dir);
+ dir = savestring (dir, len - (len > 1 && dir[len-1] == '/'));
+ if (dir[0] == '/')
+ current_directory = dir;
+ else
+ {
+ if (current_directory[0] == '/' && current_directory[1] == '\0')
+ current_directory = concat (current_directory, dir, NULL);
+ else
+ current_directory = concat (current_directory, "/", dir, NULL);
+ free (dir);
+ }
+
+ /* Now simplify any occurrences of `.' and `..' in the pathname. */
+
+ found_real_path = 0;
+ for (p = current_directory; *p;)
+ {
+ if (p[0] == '/' && p[1] == '.' && (p[2] == 0 || p[2] == '/'))
+ strcpy (p, p + 2);
+ else if (p[0] == '/' && p[1] == '.' && p[2] == '.'
+ && (p[3] == 0 || p[3] == '/'))
+ {
+ if (found_real_path)
+ {
+ /* Search backwards for the directory just before the "/.."
+ and obliterate it and the "/..". */
+ char *q = p;
+ while (q != current_directory && q[-1] != '/')
+ --q;
+
+ if (q == current_directory)
+ /* current_directory is
+ a relative pathname ("can't happen"--leave it alone). */
+ ++p;
+ else
+ {
+ strcpy (q - 1, p + 3);
+ p = q - 1;
+ }
+ }
+ else
+ /* We are dealing with leading repetitions of "/..", for example
+ "/../..", which is the Mach super-root. */
+ p += 3;
+ }
+ else
+ {
+ found_real_path = 1;
+ ++p;
+ }
+ }
+
+ forget_cached_source_info ();
+
+ if (from_tty)
+ pwd_command ((char *) 0, 1);
+}
+
+/* ARGSUSED */
+static void
+source_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ FILE *stream;
+ struct cleanup *cleanups;
+ char *file = args;
+
+ if (file == NULL)
+ {
+ error ("source command requires pathname of file to source.");
+ }
+
+ file = tilde_expand (file);
+ make_cleanup (free, file);
+
+ stream = fopen (file, FOPEN_RT);
+ 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++) != '\0')
+ {
+ 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)
+ printf_filtered ("%c", c);
+ }
+ else
+ printf_filtered ("%c", c);
+ }
+
+ /* Force this output to appear now. */
+ wrap_here ("");
+ fflush (stdout);
+}
+
+
+/* Functions to manipulate command line editing control variables. */
+
+/* Number of commands to print in each call to show_commands. */
+#define Hist_print 10
+static void
+show_commands (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;
+
+ extern struct _hist_entry *history_get PARAMS ((int));
+ extern int history_base;
+
+ /* 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;
+ }
+ /* "show commands" 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;
+ }
+
+ 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
+ "show commands +" does. This is unnecessary if arg is null,
+ because "show commands +" is not useful after "show commands". */
+ if (from_tty && args)
+ {
+ args[0] = '+';
+ args[1] = '\0';
+ }
+}
+
+/* Called by do_setshow_command. */
+/* ARGSUSED */
+static void
+set_history_size_command (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (history_size == INT_MAX)
+ unstifle_history ();
+ else if (history_size >= 0)
+ stifle_history (history_size);
+ else
+ {
+ history_size = INT_MAX;
+ error ("History size must be non-negative");
+ }
+}
+
+/* ARGSUSED */
+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);
+}
+
+/* ARGSUSED */
+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. */
+/* ARGSUSED */
+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 (signo)
+int signo;
+{
+ /* This message is based on ANSI C, section 4.7. Note that integer
+ divide by zero causes this, so "float" is a misnomer. */
+ signal (SIGFPE, float_handler);
+ error ("Erroneous arithmetic operation.");
+}
+
+/* Return whether we are running a batch file or from terminal. */
+int
+batch_mode ()
+{
+ return !(instream == stdin && ISATTY (stdin));
+}
+
+
+static void
+init_cmd_lists ()
+{
+ cmdlist = NULL;
+ infolist = NULL;
+ enablelist = NULL;
+ disablelist = NULL;
+ deletelist = NULL;
+ enablebreaklist = NULL;
+ setlist = NULL;
+ unsetlist = NULL;
+ showlist = NULL;
+ sethistlist = NULL;
+ showhistlist = NULL;
+ unsethistlist = NULL;
+#if MAINTENANCE_CMDS
+ maintenancelist = NULL;
+ maintenanceinfolist = NULL;
+ maintenanceprintlist = NULL;
+#endif
+ setprintlist = NULL;
+ showprintlist = NULL;
+ setchecklist = NULL;
+ showchecklist = NULL;
+}
+
+/* Init the history buffer. Note that we are called after the init file(s)
+ * have been read so that the user can change the history file via his
+ * .gdbinit file (for instance). The GDBHISTFILE environment variable
+ * overrides all of this.
+ */
+
+static void
+init_history()
+{
+ char *tmpenv;
+
+ tmpenv = getenv ("HISTSIZE");
+ if (tmpenv)
+ history_size = atoi (tmpenv);
+ else if (!history_size)
+ history_size = 256;
+
+ stifle_history (history_size);
+
+ tmpenv = getenv ("GDBHISTFILE");
+ if (tmpenv)
+ history_filename = savestring (tmpenv, strlen(tmpenv));
+ else if (!history_filename) {
+ /* 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", NULL);
+ }
+ read_history (history_filename);
+}
+
+static void
+init_main ()
+{
+ struct cmd_list_element *c;
+
+#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;
+
+ /* 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_completer_quote_characters = gdb_completer_quote_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 ("internals", class_maintenance, NO_FUNCTION,
+ "Maintenance commands.\n\
+Some gdb commands are provided just for use by gdb maintainers.\n\
+These commands are subject to frequent change, and may not be as\n\
+well documented as user commands.",
+ &cmdlist);
+ 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.");
+ c = add_cmd ("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.", &cmdlist);
+ c->completer = filename_completer;
+
+ 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__
+ c = add_cmd ("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.", &cmdlist);
+#else
+ /* Punt file name, we can't help it easily. */
+ c = add_cmd ("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.", &cmdlist);
+#endif
+ c->completer = filename_completer;
+
+ 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.sfunc = set_verbose;
+ set_verbose (NULL, 0, c);
+
+ add_show_from_set
+ (add_set_cmd ("editing", class_support, var_boolean, (char *)&command_editing_p,
+ "Set editing of command lines as they are typed.\n\
+Use \"on\" to enable to enable the editing, and \"off\" to disable it.\n\
+Without an argument, command line editing is enabled. To edit, use\n\
+EMACS-like or VI-like commands like control-P or ESC.", &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 ("save", 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_integer, (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.sfunc = 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 ("confirm", class_support, var_boolean,
+ (char *)&caution,
+ "Set whether to confirm potentially dangerous operations.",
+ &setlist),
+ &showlist);
+
+ add_prefix_cmd ("info", class_info, info_command,
+ "Generic command for showing things about the program being debugged.",
+ &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 about the debugger.",
+ &showlist, "show ", 0, &cmdlist);
+ /* Another way to get at the same thing. */
+ add_info ("set", show_command, "Show all GDB settings.");
+
+ add_cmd ("commands", no_class, show_commands,
+ "Show the the history of commands you typed.\n\
+You can supply a command number to start with, or a `+' to start after\n\
+the previous command number shown.",
+ &showlist);
+
+ add_cmd ("version", no_class, show_version,
+ "Show what version of GDB this is.", &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("remotedebug", no_class, var_boolean, (char *)&remote_debug,
+ "Set debugging of remote protocol.\n\
+When enabled, each packet sent or received with the remote target\n\
+is displayed.", &setlist),
+ &showlist);
+}
diff --git a/gnu/usr.bin/gdb/gdb/maint.c b/gnu/usr.bin/gdb/gdb/maint.c
new file mode 100644
index 000000000000..b5334512ab48
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/maint.c
@@ -0,0 +1,305 @@
+/* Support for GDB maintenance commands.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include "defs.h"
+
+#if MAINTENANCE_CMDS /* Entire file goes away if not including maint cmds */
+
+#include <signal.h>
+#include "command.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "demangle.h"
+#include "gdbcore.h"
+
+static void
+maintenance_command PARAMS ((char *, int));
+
+static void
+maintenance_dump_me PARAMS ((char *, int));
+
+static void
+maintenance_demangle PARAMS ((char *, int));
+
+/*
+
+LOCAL FUNCTION
+
+ maintenance_command -- access the maintenance subcommands
+
+SYNOPSIS
+
+ void maintenance_command (char *args, int from_tty)
+
+DESCRIPTION
+
+*/
+
+static void
+maintenance_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf ("\"maintenance\" must be followed by the name of a maintenance command.\n");
+ help_list (maintenancelist, "maintenance ", -1, stdout);
+}
+
+
+/* ARGSUSED */
+static void
+maintenance_dump_me (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (query ("Should GDB dump core? "))
+ {
+ signal (SIGQUIT, SIG_DFL);
+ kill (getpid (), SIGQUIT);
+ }
+}
+
+/* Someday we should allow demangling for things other than just
+ explicit strings. For example, we might want to be able to
+ specify the address of a string in either GDB's process space
+ or the debuggee's process space, and have gdb fetch and demangle
+ that string. If we have a char* pointer "ptr" that points to
+ a string, we might want to be able to given just the name and
+ have GDB demangle and print what it points to, etc. (FIXME) */
+
+static void
+maintenance_demangle (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *demangled;
+
+ if (args == NULL || *args == '\0')
+ {
+ printf ("\"maintenance demangle\" takes an argument to demangle.\n");
+ }
+ else
+ {
+ demangled = cplus_demangle (args, DMGL_ANSI | DMGL_PARAMS);
+ if (demangled != NULL)
+ {
+ printf ("%s\n", demangled);
+ free (demangled);
+ }
+ else
+ {
+ printf ("Can't demangle \"%s\"\n", args);
+ }
+ }
+}
+
+/* The "maintenance info" command is defined as a prefix, with allow_unknown 0.
+ Therefore, its own definition is called only for "maintenance info" with
+ no args. */
+
+/* ARGSUSED */
+static void
+maintenance_info_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf ("\"maintenance info\" must be followed by the name of an info command.\n");
+ help_list (maintenanceinfolist, "maintenance info ", -1, stdout);
+}
+
+static void
+print_section_table (abfd, asect, ignore)
+ bfd *abfd;
+ asection *asect;
+ PTR ignore;
+{
+ flagword flags;
+
+ flags = bfd_get_section_flags (abfd, asect);
+
+ printf_filtered (" %s",
+ local_hex_string_custom
+ ((unsigned long) bfd_section_vma (abfd, asect), "08l"));
+ printf_filtered ("->%s",
+ local_hex_string_custom
+ ((unsigned long) (bfd_section_vma (abfd, asect)
+ + bfd_section_size (abfd, asect)),
+ "08l"));
+ printf_filtered (" at %s",
+ local_hex_string_custom
+ ((unsigned long) asect->filepos, "08l"));
+ printf_filtered (": %s", bfd_section_name (abfd, asect));
+
+ if (flags & SEC_ALLOC)
+ printf_filtered (" ALLOC");
+ if (flags & SEC_LOAD)
+ printf_filtered (" LOAD");
+ if (flags & SEC_RELOC)
+ printf_filtered (" RELOC");
+ if (flags & SEC_READONLY)
+ printf_filtered (" READONLY");
+ if (flags & SEC_CODE)
+ printf_filtered (" CODE");
+ if (flags & SEC_DATA)
+ printf_filtered (" DATA");
+ if (flags & SEC_ROM)
+ printf_filtered (" ROM");
+ if (flags & SEC_CONSTRUCTOR)
+ printf_filtered (" CONSTRUCTOR");
+ if (flags & SEC_HAS_CONTENTS)
+ printf_filtered (" HAS_CONTENTS");
+ if (flags & SEC_NEVER_LOAD)
+ printf_filtered (" NEVER_LOAD");
+ if (flags & SEC_SHARED_LIBRARY)
+ printf_filtered (" SHARED_LIBRARY");
+ if (flags & SEC_IS_COMMON)
+ printf_filtered (" IS_COMMON");
+
+ printf_filtered ("\n");
+}
+
+/* ARGSUSED */
+static void
+maintenance_info_sections (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (exec_bfd)
+ {
+ printf_filtered ("Exec file:\n");
+ printf_filtered (" `%s', ", bfd_get_filename(exec_bfd));
+ wrap_here (" ");
+ printf_filtered ("file type %s.\n", bfd_get_target(exec_bfd));
+ bfd_map_over_sections(exec_bfd, print_section_table, 0);
+ }
+
+ if (core_bfd)
+ {
+ printf_filtered ("Core file:\n");
+ printf_filtered (" `%s', ", bfd_get_filename(core_bfd));
+ wrap_here (" ");
+ printf_filtered ("file type %s.\n", bfd_get_target(core_bfd));
+ bfd_map_over_sections(core_bfd, print_section_table, 0);
+ }
+}
+
+/* The "maintenance print" command is defined as a prefix, with allow_unknown
+ 0. Therefore, its own definition is called only for "maintenance print"
+ with no args. */
+
+/* ARGSUSED */
+static void
+maintenance_print_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf ("\"maintenance print\" must be followed by the name of a print command.\n");
+ help_list (maintenanceprintlist, "maintenance print ", -1, stdout);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ _initialize_maint_cmds -- initialize the process file system stuff
+
+SYNOPSIS
+
+ void _initialize_maint_cmds (void)
+
+DESCRIPTION
+
+ Do required initializations during gdb startup for using the
+ /proc file system interface.
+
+*/
+
+
+void
+_initialize_maint_cmds ()
+{
+ add_prefix_cmd ("maintenance", class_maintenance, maintenance_command,
+ "Commands for use by GDB maintainers.\n\
+Includes commands to dump specific internal GDB structures in\n\
+a human readable form, to cause GDB to deliberately dump core,\n\
+to test internal functions such as the C++ demangler, etc.",
+ &maintenancelist, "maintenance ", 0,
+ &cmdlist);
+
+ add_com_alias ("mt", "maintenance", class_maintenance, 1);
+
+ add_prefix_cmd ("info", class_maintenance, maintenance_info_command,
+ "Commands for showing internal info about the program being debugged.",
+ &maintenanceinfolist, "maintenance info ", 0,
+ &maintenancelist);
+
+ add_cmd ("sections", class_maintenance, maintenance_info_sections,
+ "List the BFD sections of the exec and core files.",
+ &maintenanceinfolist);
+
+ add_prefix_cmd ("print", class_maintenance, maintenance_print_command,
+ "Maintenance command for printing GDB internal state.",
+ &maintenanceprintlist, "maintenance print ", 0,
+ &maintenancelist);
+
+ add_cmd ("dump-me", class_maintenance, maintenance_dump_me,
+ "Get fatal error; make debugger dump its core.\n\
+GDB sets it's handling of SIGQUIT back to SIG_DFL and then sends\n\
+itself a SIGQUIT signal.",
+ &maintenancelist);
+
+ add_cmd ("demangle", class_maintenance, maintenance_demangle,
+ "Demangle a C++ mangled name.\n\
+Call internal GDB demangler routine to demangle a C++ link name\n\
+and prints the result.",
+ &maintenancelist);
+
+ add_cmd ("type", class_maintenance, maintenance_print_type,
+ "Print a type chain for a given symbol.\n\
+For each node in a type chain, print the raw data for each member of\n\
+the type structure, and the interpretation of the data.",
+ &maintenanceprintlist);
+
+ add_cmd ("symbols", class_maintenance, maintenance_print_symbols,
+ "Print dump of current symbol definitions.\n\
+Entries in the full symbol table are dumped to file OUTFILE.\n\
+If a SOURCE file is specified, dump only that file's symbols.",
+ &maintenanceprintlist);
+
+ add_cmd ("msymbols", class_maintenance, maintenance_print_msymbols,
+ "Print dump of current minimal symbol definitions.\n\
+Entries in the minimal symbol table are dumped to file OUTFILE.\n\
+If a SOURCE file is specified, dump only that file's minimal symbols.",
+ &maintenanceprintlist);
+
+ add_cmd ("psymbols", class_maintenance, maintenance_print_psymbols,
+ "Print dump of current partial symbol definitions.\n\
+Entries in the partial symbol table are dumped to file OUTFILE.\n\
+If a SOURCE file is specified, dump only that file's partial symbols.",
+ &maintenanceprintlist);
+
+ add_cmd ("objfiles", class_maintenance, maintenance_print_objfiles,
+ "Print dump of current object file definitions.",
+ &maintenanceprintlist);
+
+}
+
+#endif /* MAINTENANCE_CMDS */
diff --git a/gnu/usr.bin/gdb/gdb/mem-break.c b/gnu/usr.bin/gdb/gdb/mem-break.c
new file mode 100644
index 000000000000..74dfaa147501
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/mem-break.c
@@ -0,0 +1,104 @@
+/* Simulate breakpoints by patching locations in the target system, for GDB.
+ Copyright 1990, 1991 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by John Gilmore.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+
+#ifdef BREAKPOINT
+/* This file is only useful if BREAKPOINT is set. If not, we punt. */
+
+#include "symtab.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 unsigned char break_insn[] = BREAKPOINT;
+
+/* This is only to check that BREAKPOINT fits in BREAKPOINT_MAX bytes. */
+
+static unsigned char check_break_insn_size[BREAKPOINT_MAX] = BREAKPOINT;
+
+/* Insert a breakpoint on targets 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 (this
+ is accomplished via BREAKPOINT_MAX). */
+
+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, (char *)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);
+}
+
+
+/* FIXME: This is a hack and should depend on the debugging target.
+ See comment in breakpoint.c where this is used. */
+
+int memory_breakpoint_size = sizeof (break_insn);
+
+
+#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 */
+}
+
+int memory_breakpoint_size = -1;
+
+#endif /* BREAKPOINT */
diff --git a/gnu/usr.bin/gdb/gdb/minsyms.c b/gnu/usr.bin/gdb/gdb/minsyms.c
new file mode 100644
index 000000000000..dbb4e797d970
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/minsyms.c
@@ -0,0 +1,597 @@
+/* GDB routines for manipulating the minimal symbol tables.
+ Copyright 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+/* This file contains support routines for creating, manipulating, and
+ destroying minimal symbol tables.
+
+ Minimal symbol tables are used to hold some very basic information about
+ all defined global symbols (text, data, bss, abs, etc). The only two
+ required pieces of information are the symbol's name and the address
+ associated with that symbol.
+
+ In many cases, even if a file was compiled with no special options for
+ debugging at all, as long as was not stripped it will contain sufficient
+ information to build useful minimal symbol tables using this structure.
+
+ Even when a file contains enough debugging information to build a full
+ symbol table, these minimal symbols are still useful for quickly mapping
+ between names and addresses, and vice versa. They are also sometimes used
+ to figure out what full symbol table entries need to be read in. */
+
+
+#include "defs.h"
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "demangle.h"
+
+/* Accumulate the minimal symbols for each objfile in bunches of BUNCH_SIZE.
+ At the end, copy them all into one newly allocated location on an objfile's
+ symbol obstack. */
+
+#define BUNCH_SIZE 127
+
+struct msym_bunch
+{
+ struct msym_bunch *next;
+ struct minimal_symbol contents[BUNCH_SIZE];
+};
+
+/* Bunch currently being filled up.
+ The next field points to chain of filled bunches. */
+
+static struct msym_bunch *msym_bunch;
+
+/* Number of slots filled in current bunch. */
+
+static int msym_bunch_index;
+
+/* Total number of minimal symbols recorded so far for the objfile. */
+
+static int msym_count;
+
+/* Prototypes for local functions. */
+
+static int
+compare_minimal_symbols PARAMS ((const void *, const void *));
+
+static int
+compact_minimal_symbols PARAMS ((struct minimal_symbol *, int));
+
+/* Look through all the current minimal symbol tables and find the first
+ minimal symbol that matches NAME. If OBJF is non-NULL, it specifies a
+ particular objfile and the search is limited to that objfile. Returns
+ a pointer to the minimal symbol that matches, or NULL if no match is found.
+
+ Note: One instance where there may be duplicate minimal symbols with
+ the same name is when the symbol tables for a shared library and the
+ symbol tables for an executable contain global symbols with the same
+ names (the dynamic linker deals with the duplication). */
+
+struct minimal_symbol *
+lookup_minimal_symbol (name, objf)
+ register const char *name;
+ struct objfile *objf;
+{
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *found_symbol = NULL;
+ struct minimal_symbol *found_file_symbol = NULL;
+#ifdef IBM6000_TARGET
+ struct minimal_symbol *trampoline_symbol = NULL;
+#endif
+
+ for (objfile = object_files;
+ objfile != NULL && found_symbol == NULL;
+ objfile = objfile -> next)
+ {
+ if (objf == NULL || objf == objfile)
+ {
+ for (msymbol = objfile -> msymbols;
+ msymbol != NULL && SYMBOL_NAME (msymbol) != NULL &&
+ found_symbol == NULL;
+ msymbol++)
+ {
+ if (SYMBOL_MATCHES_NAME (msymbol, name))
+ {
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_file_text:
+ case mst_file_data:
+ case mst_file_bss:
+ /* It is file-local. If we find more than one, just
+ return the latest one (the user can't expect
+ useful behavior in that case). */
+ found_file_symbol = msymbol;
+ break;
+
+ case mst_unknown:
+#ifdef IBM6000_TARGET
+ /* I *think* all platforms using shared
+ libraries (and trampoline code) will suffer
+ this problem. Consider a case where there are
+ 5 shared libraries, each referencing `foo'
+ with a trampoline entry. When someone wants
+ to put a breakpoint on `foo' and the only
+ info we have is minimal symbol vector, we
+ want to use the real `foo', rather than one
+ of those trampoline entries. MGO */
+
+ /* If a trampoline symbol is found, we prefer to
+ keep looking for the *real* symbol. If the
+ actual symbol not found, then we'll use the
+ trampoline entry. Sorry for the machine
+ dependent code here, but I hope this will
+ benefit other platforms as well. For
+ trampoline entries, we used mst_unknown
+ earlier. Perhaps we should define a
+ `mst_trampoline' type?? */
+
+ if (trampoline_symbol == NULL)
+ trampoline_symbol = msymbol;
+ break;
+#else
+ /* FALLTHROUGH */
+#endif
+ default:
+ found_symbol = msymbol;
+ break;
+ }
+ }
+ }
+ }
+ }
+ /* External symbols are best. */
+ if (found_symbol)
+ return found_symbol;
+
+ /* File-local symbols are next best. */
+ if (found_file_symbol)
+ return found_file_symbol;
+
+ /* Symbols for IBM shared library trampolines are next best. */
+#ifdef IBM6000_TARGET
+ if (trampoline_symbol)
+ return trampoline_symbol;
+#endif
+
+ return NULL;
+}
+
+
+/* Search through the minimal symbol table for each objfile and find the
+ symbol whose address is the largest address that is still less than or
+ equal to PC. Returns a pointer to the minimal symbol if such a symbol
+ is found, or NULL if PC is not in a suitable range. Note that we need
+ to look through ALL the minimal symbol tables before deciding on the
+ symbol that comes closest to the specified PC. This is because objfiles
+ can overlap, for example objfile A has .text at 0x100 and .data at 0x40000
+ and objfile B has .text at 0x234 and .data at 0x40048. */
+
+struct minimal_symbol *
+lookup_minimal_symbol_by_pc (pc)
+ register CORE_ADDR pc;
+{
+ register int lo;
+ register int hi;
+ register int new;
+ register struct objfile *objfile;
+ register struct minimal_symbol *msymbol;
+ register struct minimal_symbol *best_symbol = NULL;
+
+ for (objfile = object_files;
+ objfile != NULL;
+ objfile = objfile -> next)
+ {
+ /* If this objfile has a minimal symbol table, go search it using
+ a binary search. Note that a minimal symbol table always consists
+ of at least two symbols, a "real" symbol and the terminating
+ "null symbol". If there are no real symbols, then there is no
+ minimal symbol table at all. */
+
+ if ((msymbol = objfile -> msymbols) != NULL)
+ {
+ lo = 0;
+ hi = objfile -> minimal_symbol_count - 1;
+
+ /* This code assumes that the minimal symbols are sorted by
+ ascending address values. If the pc value is greater than or
+ equal to the first symbol's address, then some symbol in this
+ minimal symbol table is a suitable candidate for being the
+ "best" symbol. This includes the last real symbol, for cases
+ where the pc value is larger than any address in this vector.
+
+ By iterating until the address associated with the current
+ hi index (the endpoint of the test interval) is less than
+ or equal to the desired pc value, we accomplish two things:
+ (1) the case where the pc value is larger than any minimal
+ symbol address is trivially solved, (2) the address associated
+ with the hi index is always the one we want when the interation
+ terminates. In essence, we are iterating the test interval
+ down until the pc value is pushed out of it from the high end.
+
+ Warning: this code is trickier than it would appear at first. */
+
+ /* Should also requires that pc is <= end of objfile. FIXME! */
+ if (pc >= SYMBOL_VALUE_ADDRESS (&msymbol[lo]))
+ {
+ while (SYMBOL_VALUE_ADDRESS (&msymbol[hi]) > pc)
+ {
+ /* pc is still strictly less than highest address */
+ /* Note "new" will always be >= lo */
+ new = (lo + hi) / 2;
+ if ((SYMBOL_VALUE_ADDRESS (&msymbol[new]) >= pc) ||
+ (lo == new))
+ {
+ hi = new;
+ }
+ else
+ {
+ lo = new;
+ }
+ }
+ /* The minimal symbol indexed by hi now is the best one in this
+ objfile's minimal symbol table. See if it is the best one
+ overall. */
+
+ /* Skip any absolute symbols. This is apparently what adb
+ and dbx do, and is needed for the CM-5. There are two
+ known possible problems: (1) on ELF, apparently end, edata,
+ etc. are absolute. Not sure ignoring them here is a big
+ deal, but if we want to use them, the fix would go in
+ elfread.c. (2) I think shared library entry points on the
+ NeXT are absolute. If we want special handling for this
+ it probably should be triggered by a special
+ mst_abs_or_lib or some such. */
+ while (hi >= 0
+ && msymbol[hi].type == mst_abs)
+ --hi;
+
+ if (hi >= 0
+ && ((best_symbol == NULL) ||
+ (SYMBOL_VALUE_ADDRESS (best_symbol) <
+ SYMBOL_VALUE_ADDRESS (&msymbol[hi]))))
+ {
+ best_symbol = &msymbol[hi];
+ }
+ }
+ }
+ }
+ return (best_symbol);
+}
+
+/* Prepare to start collecting minimal symbols. Note that presetting
+ msym_bunch_index to BUNCH_SIZE causes the first call to save a minimal
+ symbol to allocate the memory for the first bunch. */
+
+void
+init_minimal_symbol_collection ()
+{
+ msym_count = 0;
+ msym_bunch = NULL;
+ msym_bunch_index = BUNCH_SIZE;
+}
+
+void
+prim_record_minimal_symbol (name, address, ms_type)
+ const char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+{
+ register struct msym_bunch *new;
+ register struct minimal_symbol *msymbol;
+
+ if (msym_bunch_index == BUNCH_SIZE)
+ {
+ new = (struct msym_bunch *) xmalloc (sizeof (struct msym_bunch));
+ msym_bunch_index = 0;
+ new -> next = msym_bunch;
+ msym_bunch = new;
+ }
+ msymbol = &msym_bunch -> contents[msym_bunch_index];
+ SYMBOL_NAME (msymbol) = (char *) name;
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown);
+ SYMBOL_VALUE_ADDRESS (msymbol) = address;
+ SYMBOL_SECTION (msymbol) = -1;
+ MSYMBOL_TYPE (msymbol) = ms_type;
+ /* FIXME: This info, if it remains, needs its own field. */
+ MSYMBOL_INFO (msymbol) = NULL; /* FIXME! */
+ msym_bunch_index++;
+ msym_count++;
+}
+
+/* FIXME: Why don't we just combine this function with the one above
+ and pass it a NULL info pointer value if info is not needed? */
+
+void
+prim_record_minimal_symbol_and_info (name, address, ms_type, info, section)
+ const char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ char *info;
+ int section;
+{
+ register struct msym_bunch *new;
+ register struct minimal_symbol *msymbol;
+
+ if (msym_bunch_index == BUNCH_SIZE)
+ {
+ new = (struct msym_bunch *) xmalloc (sizeof (struct msym_bunch));
+ msym_bunch_index = 0;
+ new -> next = msym_bunch;
+ msym_bunch = new;
+ }
+ msymbol = &msym_bunch -> contents[msym_bunch_index];
+ SYMBOL_NAME (msymbol) = (char *) name;
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (msymbol, language_unknown);
+ SYMBOL_VALUE_ADDRESS (msymbol) = address;
+ SYMBOL_SECTION (msymbol) = section;
+ MSYMBOL_TYPE (msymbol) = ms_type;
+ /* FIXME: This info, if it remains, needs its own field. */
+ MSYMBOL_INFO (msymbol) = info; /* FIXME! */
+ msym_bunch_index++;
+ msym_count++;
+}
+
+/* Compare two minimal symbols by address and return a signed result based
+ on unsigned comparisons, so that we sort into unsigned numeric order. */
+
+static int
+compare_minimal_symbols (fn1p, fn2p)
+ const PTR fn1p;
+ const PTR fn2p;
+{
+ register const struct minimal_symbol *fn1;
+ register const struct minimal_symbol *fn2;
+
+ fn1 = (const struct minimal_symbol *) fn1p;
+ fn2 = (const struct minimal_symbol *) fn2p;
+
+ if (SYMBOL_VALUE_ADDRESS (fn1) < SYMBOL_VALUE_ADDRESS (fn2))
+ {
+ return (-1);
+ }
+ else if (SYMBOL_VALUE_ADDRESS (fn1) > SYMBOL_VALUE_ADDRESS (fn2))
+ {
+ return (1);
+ }
+ else
+ {
+ return (0);
+ }
+}
+
+/* Discard the currently collected minimal symbols, if any. If we wish
+ to save them for later use, we must have already copied them somewhere
+ else before calling this function.
+
+ FIXME: We could allocate the minimal symbol bunches on their own
+ obstack and then simply blow the obstack away when we are done with
+ it. Is it worth the extra trouble though? */
+
+/* ARGSUSED */
+void
+discard_minimal_symbols (foo)
+ int foo;
+{
+ register struct msym_bunch *next;
+
+ while (msym_bunch != NULL)
+ {
+ next = msym_bunch -> next;
+ free ((PTR)msym_bunch);
+ msym_bunch = next;
+ }
+}
+
+/* Compact duplicate entries out of a minimal symbol table by walking
+ through the table and compacting out entries with duplicate addresses
+ and matching names. Return the number of entries remaining.
+
+ On entry, the table resides between msymbol[0] and msymbol[mcount].
+ On exit, it resides between msymbol[0] and msymbol[result_count].
+
+ When files contain multiple sources of symbol information, it is
+ possible for the minimal symbol table to contain many duplicate entries.
+ As an example, SVR4 systems use ELF formatted object files, which
+ usually contain at least two different types of symbol tables (a
+ standard ELF one and a smaller dynamic linking table), as well as
+ DWARF debugging information for files compiled with -g.
+
+ Without compacting, the minimal symbol table for gdb itself contains
+ over a 1000 duplicates, about a third of the total table size. Aside
+ from the potential trap of not noticing that two successive entries
+ identify the same location, this duplication impacts the time required
+ to linearly scan the table, which is done in a number of places. So we
+ just do one linear scan here and toss out the duplicates.
+
+ Note that we are not concerned here about recovering the space that
+ is potentially freed up, because the strings themselves are allocated
+ on the symbol_obstack, and will get automatically freed when the symbol
+ table is freed. The caller can free up the unused minimal symbols at
+ the end of the compacted region if their allocation strategy allows it.
+
+ Also note we only go up to the next to last entry within the loop
+ and then copy the last entry explicitly after the loop terminates.
+
+ Since the different sources of information for each symbol may
+ have different levels of "completeness", we may have duplicates
+ that have one entry with type "mst_unknown" and the other with a
+ known type. So if the one we are leaving alone has type mst_unknown,
+ overwrite its type with the type from the one we are compacting out. */
+
+static int
+compact_minimal_symbols (msymbol, mcount)
+ struct minimal_symbol *msymbol;
+ int mcount;
+{
+ struct minimal_symbol *copyfrom;
+ struct minimal_symbol *copyto;
+
+ if (mcount > 0)
+ {
+ copyfrom = copyto = msymbol;
+ while (copyfrom < msymbol + mcount - 1)
+ {
+ if (SYMBOL_VALUE_ADDRESS (copyfrom) ==
+ SYMBOL_VALUE_ADDRESS ((copyfrom + 1)) &&
+ (STREQ (SYMBOL_NAME (copyfrom), SYMBOL_NAME ((copyfrom + 1)))))
+ {
+ if (MSYMBOL_TYPE((copyfrom + 1)) == mst_unknown)
+ {
+ MSYMBOL_TYPE ((copyfrom + 1)) = MSYMBOL_TYPE (copyfrom);
+ }
+ copyfrom++;
+ }
+ else
+ {
+ *copyto++ = *copyfrom++;
+ }
+ }
+ *copyto++ = *copyfrom++;
+ mcount = copyto - msymbol;
+ }
+ return (mcount);
+}
+
+/* Add the minimal symbols in the existing bunches to the objfile's official
+ minimal symbol table. In most cases there is no minimal symbol table yet
+ for this objfile, and the existing bunches are used to create one. Once
+ in a while (for shared libraries for example), we add symbols (e.g. common
+ symbols) to an existing objfile.
+
+ Because of the way minimal symbols are collected, we generally have no way
+ of knowing what source language applies to any particular minimal symbol.
+ Specifically, we have no way of knowing if the minimal symbol comes from a
+ C++ compilation unit or not. So for the sake of supporting cached
+ demangled C++ names, we have no choice but to try and demangle each new one
+ that comes in. If the demangling succeeds, then we assume it is a C++
+ symbol and set the symbol's language and demangled name fields
+ appropriately. Note that in order to avoid unnecessary demanglings, and
+ allocating obstack space that subsequently can't be freed for the demangled
+ names, we mark all newly added symbols with language_auto. After
+ compaction of the minimal symbols, we go back and scan the entire minimal
+ symbol table looking for these new symbols. For each new symbol we attempt
+ to demangle it, and if successful, record it as a language_cplus symbol
+ and cache the demangled form on the symbol obstack. Symbols which don't
+ demangle are marked as language_unknown symbols, which inhibits future
+ attempts to demangle them if we later add more minimal symbols. */
+
+void
+install_minimal_symbols (objfile)
+ struct objfile *objfile;
+{
+ register int bindex;
+ register int mcount;
+ register struct msym_bunch *bunch;
+ register struct minimal_symbol *msymbols;
+ int alloc_count;
+ register char leading_char;
+
+ if (msym_count > 0)
+ {
+ /* Allocate enough space in the obstack, into which we will gather the
+ bunches of new and existing minimal symbols, sort them, and then
+ compact out the duplicate entries. Once we have a final table,
+ we will give back the excess space. */
+
+ alloc_count = msym_count + objfile->minimal_symbol_count + 1;
+ obstack_blank (&objfile->symbol_obstack,
+ alloc_count * sizeof (struct minimal_symbol));
+ msymbols = (struct minimal_symbol *)
+ obstack_base (&objfile->symbol_obstack);
+
+ /* Copy in the existing minimal symbols, if there are any. */
+
+ if (objfile->minimal_symbol_count)
+ memcpy ((char *)msymbols, (char *)objfile->msymbols,
+ objfile->minimal_symbol_count * sizeof (struct minimal_symbol));
+
+ /* Walk through the list of minimal symbol bunches, adding each symbol
+ to the new contiguous array of symbols. Note that we start with the
+ current, possibly partially filled bunch (thus we use the current
+ msym_bunch_index for the first bunch we copy over), and thereafter
+ each bunch is full. */
+
+ mcount = objfile->minimal_symbol_count;
+ leading_char = bfd_get_symbol_leading_char (objfile->obfd);
+
+ for (bunch = msym_bunch; bunch != NULL; bunch = bunch -> next)
+ {
+ for (bindex = 0; bindex < msym_bunch_index; bindex++, mcount++)
+ {
+ msymbols[mcount] = bunch -> contents[bindex];
+ SYMBOL_LANGUAGE (&msymbols[mcount]) = language_auto;
+ if (SYMBOL_NAME (&msymbols[mcount])[0] == leading_char)
+ {
+ SYMBOL_NAME(&msymbols[mcount])++;
+ }
+ }
+ msym_bunch_index = BUNCH_SIZE;
+ }
+
+ /* Sort the minimal symbols by address. */
+
+ qsort (msymbols, mcount, sizeof (struct minimal_symbol),
+ compare_minimal_symbols);
+
+ /* Compact out any duplicates, and free up whatever space we are
+ no longer using. */
+
+ mcount = compact_minimal_symbols (msymbols, mcount);
+
+ obstack_blank (&objfile->symbol_obstack,
+ (mcount + 1 - alloc_count) * sizeof (struct minimal_symbol));
+ msymbols = (struct minimal_symbol *)
+ obstack_finish (&objfile->symbol_obstack);
+
+ /* We also terminate the minimal symbol table with a "null symbol",
+ which is *not* included in the size of the table. This makes it
+ easier to find the end of the table when we are handed a pointer
+ to some symbol in the middle of it. Zero out the fields in the
+ "null symbol" allocated at the end of the array. Note that the
+ symbol count does *not* include this null symbol, which is why it
+ is indexed by mcount and not mcount-1. */
+
+ SYMBOL_NAME (&msymbols[mcount]) = NULL;
+ SYMBOL_VALUE_ADDRESS (&msymbols[mcount]) = 0;
+ MSYMBOL_INFO (&msymbols[mcount]) = NULL;
+ MSYMBOL_TYPE (&msymbols[mcount]) = mst_unknown;
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (&msymbols[mcount], language_unknown);
+
+ /* Attach the minimal symbol table to the specified objfile.
+ The strings themselves are also located in the symbol_obstack
+ of this objfile. */
+
+ objfile -> minimal_symbol_count = mcount;
+ objfile -> msymbols = msymbols;
+
+ /* Now walk through all the minimal symbols, selecting the newly added
+ ones and attempting to cache their C++ demangled names. */
+
+ for ( ; mcount-- > 0 ; msymbols++)
+ {
+ SYMBOL_INIT_DEMANGLED_NAME (msymbols, &objfile->symbol_obstack);
+ }
+ }
+}
+
diff --git a/gnu/usr.bin/gdb/gdb/mipsread.c b/gnu/usr.bin/gdb/gdb/mipsread.c
new file mode 100644
index 000000000000..199092bb5c39
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/mipsread.c
@@ -0,0 +1,3653 @@
+/* Read a symbol table in MIPS' format (Third-Eye).
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993 Free Software
+ Foundation, Inc.
+ Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU. Major work
+ by Per Bothner, John Gilmore and Ian Lance Taylor at Cygnus Support.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This module provides three functions: mipscoff_symfile_init,
+ which initializes to read a symbol file; mipscoff_new_init, which
+ discards existing cached information when all symbols are being
+ discarded; and mipscoff_symfile_read, which reads a symbol table
+ from a file.
+
+ mipscoff_symfile_read only does the minimum work necessary for letting the
+ user "name" things symbolically; it does not read the entire symtab.
+ Instead, it reads the external and static symbols and puts 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 symbols
+ for real. mipscoff_psymtab_to_symtab() is called indirectly through
+ a pointer in the psymtab to do this.
+
+ ECOFF symbol tables are mostly written in the byte order of the
+ target machine. However, one section of the table (the auxiliary
+ symbol information) is written in the host byte order. There is a
+ bit in the other symbol info which describes which host byte order
+ was used. ECOFF thereby takes the trophy from Intel `b.out' for
+ the most brain-dead adaptation of a file format to byte order.
+
+ This module can read all four of the known byte-order combinations,
+ on any type of host. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "obstack.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "complaints.h"
+
+/* These are needed if the tm.h file does not contain the necessary
+ mips specific definitions. */
+
+#ifndef MIPS_EFI_SYMBOL_NAME
+#define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__"
+#include "coff/sym.h"
+#include "coff/symconst.h"
+typedef struct mips_extra_func_info {
+ long numargs;
+ PDR pdr;
+} *mips_extra_func_info_t;
+#ifndef RA_REGNUM
+#define RA_REGNUM 0
+#endif
+#endif
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#include "gdb-stabs.h"
+
+#include "bfd.h"
+
+#include "coff/internal.h"
+#include "coff/ecoff.h" /* COFF-like aspects of ecoff files */
+
+/* FIXME: coff/internal.h and aout/aout64.h both define N_ABS. We
+ want the definition from aout/aout64.h. */
+#undef N_ABS
+
+#include "libaout.h" /* Private BFD a.out information. */
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h" /* STABS information */
+
+/* FIXME: libcoff.h and libaout.h both define a couple of macros. We
+ don't use them. */
+#undef exec_hdr
+#undef obj_sym_filepos
+
+#include "libcoff.h" /* Private BFD COFF information. */
+#include "libecoff.h" /* Private BFD ECOFF information. */
+
+#include "expression.h"
+#include "language.h" /* Needed inside partial-stab.h */
+
+/* Provide a default mapping from a ecoff register number to a gdb REGNUM. */
+#ifndef ECOFF_REG_TO_REGNUM
+#define ECOFF_REG_TO_REGNUM(num) (num)
+#endif
+
+/* Information is passed among various mipsread routines for accessing
+ symbol files. A pointer to this structure is kept in the sym_private
+ field of the objfile struct. */
+
+struct ecoff_symfile_info {
+ struct mips_pending **pending_list;
+};
+#define ECOFF_SYMFILE_INFO(o) ((struct ecoff_symfile_info *)((o)->sym_private))
+#define ECOFF_PENDING_LIST(o) (ECOFF_SYMFILE_INFO(o)->pending_list)
+
+
+/* Each partial symbol table entry contains a pointer to private data
+ for the read_symtab() function to use when expanding a partial
+ symbol table entry to a full symbol table entry.
+
+ For mipsread this structure contains the index of the FDR that this
+ psymtab represents and a pointer to the BFD that the psymtab was
+ created from. */
+
+#define PST_PRIVATE(p) ((struct symloc *)(p)->read_symtab_private)
+#define FDR_IDX(p) (PST_PRIVATE(p)->fdr_idx)
+#define CUR_BFD(p) (PST_PRIVATE(p)->cur_bfd)
+
+struct symloc
+{
+ int fdr_idx;
+ bfd *cur_bfd;
+ EXTR *extern_tab; /* Pointer to external symbols for this file. */
+ int extern_count; /* Size of extern_tab. */
+ enum language pst_language;
+};
+
+/* Things we import explicitly from other modules */
+
+extern int info_verbose;
+
+/* Various complaints about symbol reading that don't abort the process */
+
+struct complaint bad_file_number_complaint =
+{"bad file number %d", 0, 0};
+
+struct complaint index_complaint =
+{"bad aux index at symbol %s", 0, 0};
+
+struct complaint aux_index_complaint =
+{"bad proc end in aux found from symbol %s", 0, 0};
+
+struct complaint block_index_complaint =
+{"bad aux index at block symbol %s", 0, 0};
+
+struct complaint unknown_ext_complaint =
+{"unknown external symbol %s", 0, 0};
+
+struct complaint unknown_sym_complaint =
+{"unknown local symbol %s", 0, 0};
+
+struct complaint unknown_st_complaint =
+{"with type %d", 0, 0};
+
+struct complaint block_overflow_complaint =
+{"block containing %s overfilled", 0, 0};
+
+struct complaint basic_type_complaint =
+{"cannot map MIPS basic type 0x%x for %s", 0, 0};
+
+struct complaint unknown_type_qual_complaint =
+{"unknown type qualifier 0x%x", 0, 0};
+
+struct complaint array_index_type_complaint =
+{"illegal array index type for %s, assuming int", 0, 0};
+
+struct complaint bad_tag_guess_complaint =
+{"guessed tag type of %s incorrectly", 0, 0};
+
+struct complaint block_member_complaint =
+{"declaration block contains unhandled symbol type %d", 0, 0};
+
+struct complaint stEnd_complaint =
+{"stEnd with storage class %d not handled", 0, 0};
+
+struct complaint unknown_mips_symtype_complaint =
+{"unknown symbol type 0x%x", 0, 0};
+
+struct complaint stab_unknown_complaint =
+{"unknown stabs symbol %s", 0, 0};
+
+struct complaint pdr_for_nonsymbol_complaint =
+{"PDR for %s, but no symbol", 0, 0};
+
+struct complaint pdr_static_symbol_complaint =
+{"can't handle PDR for static proc at 0x%lx", 0, 0};
+
+struct complaint bad_setjmp_pdr_complaint =
+{"fixing bad setjmp PDR from libc", 0, 0};
+
+struct complaint bad_fbitfield_complaint =
+{"can't handle TIR fBitfield for %s", 0, 0};
+
+struct complaint bad_continued_complaint =
+{"illegal TIR continued for %s", 0, 0};
+
+struct complaint bad_rfd_entry_complaint =
+{"bad rfd entry for %s: file %d, index %d", 0, 0};
+
+struct complaint unexpected_type_code_complaint =
+{"unexpected type code for %s", 0, 0};
+
+struct complaint unable_to_cross_ref_complaint =
+{"unable to cross ref btTypedef for %s", 0, 0};
+
+struct complaint illegal_forward_tq0_complaint =
+{"illegal tq0 in forward typedef for %s", 0, 0};
+
+struct complaint illegal_forward_bt_complaint =
+{"illegal bt %d in forward typedef for %s", 0, 0};
+
+struct complaint bad_linetable_guess_complaint =
+{"guessed size of linetable for %s incorrectly", 0, 0};
+
+/* Macros and extra defs */
+
+/* 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)))
+
+/* Things that really are local to this module */
+
+/* Remember what we deduced to be the source language of this psymtab. */
+
+static enum language psymtab_language = language_unknown;
+
+/* Current BFD. */
+
+static bfd *cur_bfd;
+
+/* 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;
+
+/* Pseudo symbol to use when putting stabs into the symbol table. */
+
+static char stabs_symbol[] = STABS_SYMBOL;
+
+/* 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;
+
+/* Forward declarations */
+
+static void
+read_mips_symtab PARAMS ((struct objfile *, struct section_offsets *));
+
+static void
+read_the_mips_symtab PARAMS ((bfd *));
+
+static int
+upgrade_type PARAMS ((int, struct type **, int, union aux_ext *, int, char *));
+
+static void
+parse_partial_symbols PARAMS ((struct objfile *,
+ struct section_offsets *));
+
+static int
+cross_ref PARAMS ((int, union aux_ext *, struct type **, enum type_code,
+ char **, int, char *));
+
+static void
+fixup_sigtramp PARAMS ((void));
+
+static struct symbol *
+new_symbol PARAMS ((char *));
+
+static struct type *
+new_type PARAMS ((char *));
+
+static struct block *
+new_block PARAMS ((int));
+
+static struct symtab *
+new_symtab PARAMS ((char *, int, int, struct objfile *));
+
+static struct linetable *
+new_linetable PARAMS ((int));
+
+static struct blockvector *
+new_bvect PARAMS ((int));
+
+static int
+parse_symbol PARAMS ((SYMR *, union aux_ext *, char *, int));
+
+static struct type *
+parse_type PARAMS ((int, union aux_ext *, unsigned int, int *, int, char *));
+
+static struct symbol *
+mylookup_symbol PARAMS ((char *, struct block *, enum namespace,
+ enum address_class));
+
+static struct block *
+shrink_block PARAMS ((struct block *, struct symtab *));
+
+static PTR
+xzalloc PARAMS ((unsigned int));
+
+static void
+sort_blocks PARAMS ((struct symtab *));
+
+static int
+compare_blocks PARAMS ((const void *, const void *));
+
+static struct partial_symtab *
+new_psymtab PARAMS ((char *, struct objfile *));
+
+static void
+psymtab_to_symtab_1 PARAMS ((struct partial_symtab *, char *));
+
+static void
+add_block PARAMS ((struct block *, struct symtab *));
+
+static void
+add_symbol PARAMS ((struct symbol *, struct block *));
+
+static int
+add_line PARAMS ((struct linetable *, int, CORE_ADDR, int));
+
+static struct linetable *
+shrink_linetable PARAMS ((struct linetable *));
+
+static char *
+mips_next_symbol_text PARAMS ((void));
+
+/* Things we export to other modules */
+
+/* Address bounds for the signal trampoline in inferior, if any */
+/* FIXME: Nothing really seems to use this. Why is it here? */
+
+CORE_ADDR sigtramp_address, sigtramp_end;
+
+static void
+mipscoff_new_init (ignore)
+ struct objfile *ignore;
+{
+ sigtramp_address = 0;
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+static void
+mipscoff_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sym_private != NULL)
+ {
+ mfree (objfile->md, objfile->sym_private);
+ }
+ objfile->sym_private = (PTR)
+ xmmalloc (objfile->md, sizeof (struct ecoff_symfile_info));
+}
+
+static void
+mipscoff_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ struct cleanup * back_to;
+
+ init_minimal_symbol_collection ();
+ back_to = make_cleanup (discard_minimal_symbols, 0);
+
+ /* Now that the executable file is positioned at symbol table,
+ process it and define symbols accordingly. */
+
+ read_mips_symtab (objfile, section_offsets);
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ do_cleanups (back_to);
+}
+
+/* Perform any local cleanups required when we are done with a particular
+ objfile. I.E, we are in the process of discarding all symbol information
+ for an objfile, freeing up all memory held for it, and unlinking the
+ objfile struct from the global list of known objfiles. */
+
+static void
+mipscoff_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sym_private != NULL)
+ {
+ mfree (objfile->md, objfile->sym_private);
+ }
+
+ cur_bfd = 0;
+}
+
+/* Allocate zeroed memory */
+
+static PTR
+xzalloc (size)
+ unsigned int size;
+{
+ PTR p = xmalloc (size);
+
+ memset (p, 0, 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 */
+
+static void
+mipscoff_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+
+ if (!pst)
+ return;
+
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...", pst->filename);
+ fflush (stdout);
+ }
+
+ next_symbol_text_func = mips_next_symbol_text;
+
+ psymtab_to_symtab_1 (pst, pst->filename);
+
+ /* 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 (pst->objfile);
+
+ if (info_verbose)
+ printf_filtered ("done.\n");
+}
+
+/* Exported procedure: Is PC in the signal trampoline code */
+
+int
+in_sigtramp (pc, ignore)
+ CORE_ADDR pc;
+ char *ignore; /* function name */
+{
+ if (sigtramp_address == 0)
+ fixup_sigtramp ();
+ return (pc >= sigtramp_address && pc < sigtramp_end);
+}
+
+/* File-level interface functions */
+
+/* Read the symtab information from file ABFD into memory. */
+
+static void
+read_the_mips_symtab (abfd)
+ bfd *abfd;
+{
+ if (ecoff_slurp_symbolic_info (abfd) == false)
+ error ("Error reading symbol table: %s", bfd_errmsg (bfd_error));
+}
+
+/* Find a file descriptor given its index RF relative to a file CF */
+
+static FDR *
+get_rfd (cf, rf)
+ int cf, rf;
+{
+ FDR *fdrs;
+ register FDR *f;
+ RFDT rfd;
+
+ fdrs = ecoff_data (cur_bfd)->fdr;
+ f = fdrs + cf;
+ /* Object files do not have the RFD table, all refs are absolute */
+ if (f->rfdBase == 0)
+ return fdrs + rf;
+ (*ecoff_backend (cur_bfd)->swap_rfd_in)
+ (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_rfd
+ + (f->rfdBase + rf) * ecoff_backend (cur_bfd)->external_rfd_size),
+ &rfd);
+ return fdrs + rfd;
+}
+
+/* Return a safer print NAME for a file descriptor */
+
+static char *
+fdr_name (f)
+ FDR *f;
+{
+ if (f->rss == -1)
+ return "<stripped file>";
+ if (f->rss == 0)
+ return "<NFY>";
+ return ecoff_data (cur_bfd)->ss + f->issBase + f->rss;
+}
+
+
+/* Read in and parse the symtab of the file OBJFILE. Symbols from
+ different sections are relocated via the SECTION_OFFSETS. */
+
+static void
+read_mips_symtab (objfile, section_offsets)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+ cur_bfd = objfile->obfd;
+
+ read_the_mips_symtab (objfile->obfd);
+
+ parse_partial_symbols (objfile, section_offsets);
+
+#if 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.\n",
+ objfile->name);
+ printf ("You should compile with -g2 or -g3 for best debugging support.\n");
+ fflush (stdout);
+ }
+#endif
+}
+
+/* Local utilities */
+
+/* Map of FDR indexes to partial symtabs */
+
+struct pst_map
+{
+ struct partial_symtab *pst; /* the psymtab proper */
+ long n_globals; /* exported globals (external symbols) */
+ long globals_offset; /* cumulative */
+};
+
+
+/* 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 cur_field; /* Field number in cur_type. */
+ CORE_ADDR procadr; /* Start addres of this procedure */
+ int numargs; /* Its argument count */
+}
+
+ *top_stack; /* Top stack ptr */
+
+
+/* Enter a new lexical context */
+
+static void
+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 void
+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 */
+
+struct mips_pending
+{
+ struct mips_pending *next; /* link */
+ char *s; /* the unswapped symbol */
+ struct type *t; /* its partial type descriptor */
+};
+
+
+/* Check whether we already saw symbol SH in file FH */
+
+static struct mips_pending *
+is_pending_symbol (fh, sh)
+ FDR *fh;
+ char *sh;
+{
+ int f_idx = fh - ecoff_data (cur_bfd)->fdr;
+ register struct mips_pending *p;
+ struct mips_pending **pending_list = ECOFF_PENDING_LIST (current_objfile);
+
+ /* 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;
+}
+
+/* Add a new symbol SH of type T */
+
+static void
+add_pending (fh, sh, t)
+ FDR *fh;
+ char *sh;
+ struct type *t;
+{
+ int f_idx = fh - ecoff_data (cur_bfd)->fdr;
+ struct mips_pending *p = is_pending_symbol (fh, sh);
+
+ /* Make sure we do not make duplicates */
+ if (!p)
+ {
+ struct mips_pending **pending_list = ECOFF_PENDING_LIST (current_objfile);
+
+ p = ((struct mips_pending *)
+ obstack_alloc (&current_objfile->psymbol_obstack,
+ sizeof (struct mips_pending)));
+ p->s = sh;
+ p->t = t;
+ p->next = pending_list[f_idx];
+ pending_list[f_idx] = p;
+ }
+}
+
+
+/* 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. Argument
+ AX is the base pointer of aux symbols for this file (fh->iauxBase).
+ EXT_SH points to the unswapped symbol, which is needed for struct,
+ union, etc., types; it is NULL for an EXTR. BIGEND says whether
+ aux symbols are big-endian or little-endian. Return count of
+ SYMR's handled (normally one). */
+
+static int
+parse_symbol (sh, ax, ext_sh, bigend)
+ SYMR *sh;
+ union aux_ext *ax;
+ char *ext_sh;
+ int bigend;
+{
+ const bfd_size_type external_sym_size
+ = ecoff_backend (cur_bfd)->external_sym_size;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) =
+ ecoff_backend (cur_bfd)->swap_sym_in;
+ char *name;
+ struct symbol *s;
+ struct block *b;
+ struct mips_pending *pend;
+ struct type *t;
+ struct field *f;
+ int count = 1;
+ enum address_class class;
+ TIR tir;
+ long svalue = sh->value;
+ int bitsize;
+
+ if (ext_sh == (char *) NULL)
+ name = ecoff_data (cur_bfd)->ssext + sh->iss;
+ else
+ name = ecoff_data (cur_bfd)->ss + cur_fdr->issBase + sh->iss;
+
+ switch (sh->st)
+ {
+ case stNil:
+ break;
+
+ case stGlobal: /* external symbol, goes into global block */
+ class = LOC_STATIC;
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st),
+ GLOBAL_BLOCK);
+ s = new_symbol (name);
+ SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value;
+ goto data;
+
+ case stStatic: /* static data, goes into current block. */
+ class = LOC_STATIC;
+ b = top_stack->cur_block;
+ s = new_symbol (name);
+ if (sh->sc == scCommon)
+ {
+ /* It is a FORTRAN common block. At least for SGI Fortran the
+ address is not in the symbol; we need to fix it later in
+ scan_file_globals. */
+ int bucket = hashname (SYMBOL_NAME (s));
+ SYMBOL_VALUE_CHAIN (s) = global_sym_chain[bucket];
+ global_sym_chain[bucket] = s;
+ }
+ else
+ SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value;
+ goto data;
+
+ case stLocal: /* local variable, goes into current block */
+ if (sh->sc == scRegister)
+ {
+ class = LOC_REGISTER;
+ svalue = ECOFF_REG_TO_REGNUM (svalue);
+ }
+ else
+ class = LOC_LOCAL;
+ b = top_stack->cur_block;
+ s = new_symbol (name);
+ SYMBOL_VALUE (s) = svalue;
+
+ data: /* Common code for symbols describing data */
+ 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 (cur_fd, ax, sh->index, 0, bigend, name);
+ /* Value of a data symbol is its memory address */
+ break;
+
+ case stParam: /* arg to procedure, goes into current block */
+ max_gdbinfo++;
+ top_stack->numargs++;
+
+ /* Special GNU C++ name. */
+ if (name[0] == CPLUS_MARKER && name[1] == 't' && name[2] == 0)
+ name = "this"; /* FIXME, not alloc'd in obstack */
+ s = new_symbol (name);
+
+ SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
+ switch (sh->sc)
+ {
+ case scRegister:
+ /* Pass by value in register. */
+ SYMBOL_CLASS(s) = LOC_REGPARM;
+ svalue = ECOFF_REG_TO_REGNUM (svalue);
+ break;
+ case scVar:
+ /* Pass by reference on stack. */
+ SYMBOL_CLASS(s) = LOC_REF_ARG;
+ break;
+ case scVarRegister:
+ /* Pass by reference in register. */
+ SYMBOL_CLASS(s) = LOC_REGPARM_ADDR;
+ svalue = ECOFF_REG_TO_REGNUM (svalue);
+ break;
+ default:
+ /* Pass by value on stack. */
+ SYMBOL_CLASS(s) = LOC_ARG;
+ break;
+ }
+ SYMBOL_VALUE (s) = svalue;
+ SYMBOL_TYPE (s) = parse_type (cur_fd, ax, sh->index, 0, bigend, name);
+ add_symbol (s, top_stack->cur_block);
+#if 0
+ /* FIXME: This has not been tested. See dbxread.c */
+ /* Add the type of this parameter to the function/procedure
+ type of this block. */
+ add_param_to_type (&top_stack->cur_block->function->type, s);
+#endif
+ break;
+
+ case stLabel: /* label, goes into current block */
+ s = new_symbol (name);
+ SYMBOL_NAMESPACE (s) = VAR_NAMESPACE; /* so that it can be used */
+ SYMBOL_CLASS (s) = LOC_LABEL; /* but not misused */
+ SYMBOL_VALUE_ADDRESS (s) = (CORE_ADDR) sh->value;
+ SYMBOL_TYPE (s) = builtin_type_int;
+ add_symbol (s, top_stack->cur_block);
+ break;
+
+ case stProc: /* Procedure, usually goes into global block */
+ case stStaticProc: /* Static procedure, goes into current block */
+ s = new_symbol (name);
+ 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 (cur_fd, ax, sh->index + 1, 0, bigend, name);
+ b = top_stack->cur_block;
+ if (sh->st == stProc)
+ {
+ struct blockvector *bv = BLOCKVECTOR (top_stack->cur_st);
+ /* The next test should normally be true,
+ but provides a hook for nested functions
+ (which we don't want to make global). */
+ if (b == BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK))
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ }
+ add_symbol (s, b);
+
+ /* Make a type for the procedure itself */
+#if 0
+ /* FIXME: This has not been tested yet! See dbxread.c */
+ /* Generate a template for the type of this function. The
+ types of the arguments will be added as we read the symbol
+ table. */
+ memcpy (lookup_function_type (t), SYMBOL_TYPE (s), sizeof (struct type));
+#else
+ SYMBOL_TYPE (s) = lookup_function_type (t);
+#endif
+
+ /* 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->cur_field = -1;
+ top_stack->procadr = sh->value;
+ top_stack->numargs = 0;
+ break;
+
+ /* Beginning of code for structure, union, and enum definitions.
+ They all share a common set of local variables, defined here. */
+ {
+ enum type_code type_code;
+ char *ext_tsym;
+ int nfields;
+ long max_value;
+ struct field *f;
+
+ case stStruct: /* Start a block defining a struct type */
+ type_code = TYPE_CODE_STRUCT;
+ goto structured_common;
+
+ case stUnion: /* Start a block defining a union type */
+ type_code = TYPE_CODE_UNION;
+ goto structured_common;
+
+ case stEnum: /* Start a block defining an enum type */
+ type_code = TYPE_CODE_ENUM;
+ goto structured_common;
+
+ case stBlock: /* Either a lexical block, or some type */
+ if (sh->sc != scInfo && sh->sc != scCommon)
+ goto case_stBlock_code; /* Lexical block */
+
+ type_code = TYPE_CODE_UNDEF; /* We have a type. */
+
+ /* Common code for handling struct, union, enum, and/or as-yet-
+ unknown-type blocks of info about structured data. `type_code'
+ has been set to the proper TYPE_CODE, if we know it. */
+ structured_common:
+ push_parse_stack ();
+ top_stack->blocktype = stBlock;
+
+ /* First count the number of fields and the highest value. */
+ nfields = 0;
+ max_value = 0;
+ for (ext_tsym = ext_sh + external_sym_size;
+ ;
+ ext_tsym += external_sym_size)
+ {
+ SYMR tsym;
+
+ (*swap_sym_in) (cur_bfd, ext_tsym, &tsym);
+
+ switch (tsym.st)
+ {
+ case stEnd:
+ goto end_of_fields;
+
+ case stMember:
+ if (nfields == 0 && type_code == TYPE_CODE_UNDEF)
+ /* If the type of the member is Nil (or Void),
+ without qualifiers, assume the tag is an
+ enumeration. */
+ if (tsym.index == indexNil)
+ type_code = TYPE_CODE_ENUM;
+ else
+ {
+ ecoff_swap_tir_in (bigend,
+ &ax[tsym.index].a_ti,
+ &tir);
+ if ((tir.bt == btNil || tir.bt == btVoid)
+ && tir.tq0 == tqNil)
+ type_code = TYPE_CODE_ENUM;
+ }
+ nfields++;
+ if (tsym.value > max_value)
+ max_value = tsym.value;
+ break;
+
+ case stBlock:
+ case stUnion:
+ case stEnum:
+ case stStruct:
+ {
+#if 0
+ /* This is a no-op; is it trying to tell us something
+ we should be checking? */
+ if (tsym.sc == scVariant); /*UNIMPLEMENTED*/
+#endif
+ if (tsym.index != 0)
+ {
+ /* This is something like a struct within a
+ struct. Skip over the fields of the inner
+ struct. The -1 is because the for loop will
+ increment ext_tsym. */
+ ext_tsym = ((char *) ecoff_data (cur_bfd)->external_sym
+ + ((cur_fdr->isymBase + tsym.index - 1)
+ * external_sym_size));
+ }
+ }
+ break;
+
+ case stTypedef:
+ /* mips cc puts out a typedef for struct x if it is not yet
+ defined when it encounters
+ struct y { struct x *xp; };
+ Just ignore it. */
+ break;
+
+ default:
+ complain (&block_member_complaint, tsym.st);
+ }
+ }
+ end_of_fields:;
+
+ /* In an stBlock, there is no way to distinguish structs,
+ unions, and enums at this point. This is a bug in the
+ original design (that has been fixed with the recent
+ addition of the stStruct, stUnion, and stEnum symbol
+ types.) The way you can tell is if/when you see a variable
+ or field of that type. In that case the variable's type
+ (in the AUX table) says if the type is struct, union, or
+ enum, and points back to the stBlock here. So you can
+ patch the tag kind up later - but only if there actually is
+ a variable or field of that type.
+
+ So until we know for sure, we will guess at this point.
+ The heuristic is:
+ If the first member has index==indexNil or a void type,
+ assume we have an enumeration.
+ Otherwise, if there is more than one member, and all
+ the members have offset 0, assume we have a union.
+ Otherwise, assume we have a struct.
+
+ The heuristic could guess wrong in the case of of an
+ enumeration with no members or a union with one (or zero)
+ members, or when all except the last field of a struct have
+ width zero. These are uncommon and/or illegal situations,
+ and in any case guessing wrong probably doesn't matter
+ much.
+
+ But if we later do find out we were wrong, we fixup the tag
+ kind. Members of an enumeration must be handled
+ differently from struct/union fields, and that is harder to
+ patch up, but luckily we shouldn't need to. (If there are
+ any enumeration members, we can tell for sure it's an enum
+ here.) */
+
+ if (type_code == TYPE_CODE_UNDEF)
+ if (nfields > 1 && max_value == 0)
+ type_code = TYPE_CODE_UNION;
+ else
+ type_code = TYPE_CODE_STRUCT;
+
+ /* Create a new type or use the pending type. */
+ pend = is_pending_symbol (cur_fdr, ext_sh);
+ if (pend == (struct mips_pending *) NULL)
+ {
+ t = new_type (NULL);
+ add_pending (cur_fdr, ext_sh, t);
+ }
+ else
+ t = pend->t;
+
+ /* Alpha cc unnamed structs do not get a tag name. */
+ if (sh->iss == 0)
+ TYPE_TAG_NAME (t) = NULL;
+ else
+ TYPE_TAG_NAME (t) = obconcat (&current_objfile->symbol_obstack,
+ "", "", name);
+
+ TYPE_CODE (t) = type_code;
+ TYPE_LENGTH (t) = sh->value;
+ TYPE_NFIELDS (t) = nfields;
+ TYPE_FIELDS (t) = f = ((struct field *)
+ TYPE_ALLOC (t,
+ nfields * sizeof (struct field)));
+
+ if (type_code == TYPE_CODE_ENUM)
+ {
+ /* This is a non-empty enum. */
+ for (ext_tsym = ext_sh + external_sym_size;
+ ;
+ ext_tsym += external_sym_size)
+ {
+ SYMR tsym;
+ struct symbol *enum_sym;
+
+ (*swap_sym_in) (cur_bfd, ext_tsym, &tsym);
+
+ if (tsym.st != stMember)
+ break;
+
+ f->bitpos = tsym.value;
+ f->type = t;
+ f->name = (ecoff_data (cur_bfd)->ss
+ + cur_fdr->issBase
+ + tsym.iss);
+ f->bitsize = 0;
+
+ enum_sym = ((struct symbol *)
+ obstack_alloc (&current_objfile->symbol_obstack,
+ sizeof (struct symbol)));
+ memset ((PTR) enum_sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (enum_sym) = f->name;
+ SYMBOL_CLASS (enum_sym) = LOC_CONST;
+ SYMBOL_TYPE (enum_sym) = t;
+ SYMBOL_NAMESPACE (enum_sym) = VAR_NAMESPACE;
+ SYMBOL_VALUE (enum_sym) = tsym.value;
+ add_symbol (enum_sym, top_stack->cur_block);
+
+ /* Skip the stMembers that we've handled. */
+ count++;
+ f++;
+ }
+ }
+ /* make this the current type */
+ top_stack->cur_type = t;
+ top_stack->cur_field = 0;
+
+ /* Do not create a symbol for alpha cc unnamed structs. */
+ if (sh->iss == 0)
+ break;
+ s = new_symbol (name);
+ SYMBOL_NAMESPACE (s) = STRUCT_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_TYPEDEF;
+ SYMBOL_VALUE (s) = 0;
+ SYMBOL_TYPE (s) = t;
+
+ /* gcc puts out an empty struct for an opaque struct definitions. */
+ if (TYPE_NFIELDS (t) == 0)
+ {
+ TYPE_FLAGS (t) |= TYPE_FLAG_STUB;
+ SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
+ }
+ add_symbol (s, top_stack->cur_block);
+ break;
+
+ /* End of local variables shared by struct, union, enum, and
+ block (as yet unknown struct/union/enum) processing. */
+ }
+
+ case_stBlock_code:
+ /* beginnning of (code) block. Value of symbol
+ is the displacement from procedure start */
+ push_parse_stack ();
+ top_stack->blocktype = stBlock;
+ 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 || sh->sc == scCommon)
+ {
+ /* 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 mips_extra_func_info *e;
+ struct block *b;
+ int i;
+
+ BLOCK_END (top_stack->cur_block) += sh->value; /* size */
+
+ /* Make up special symbol to contain procedure specific info */
+ s = new_symbol (MIPS_EFI_SYMBOL_NAME);
+ SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_CONST;
+ SYMBOL_TYPE (s) = builtin_type_void;
+ e = ((struct mips_extra_func_info *)
+ obstack_alloc (&current_objfile->symbol_obstack,
+ sizeof (struct mips_extra_func_info)));
+ SYMBOL_VALUE (s) = (long) e;
+ e->numargs = top_stack->numargs;
+ add_symbol (s, top_stack->cur_block);
+
+ /* 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;
+ shrink_block (top_stack->cur_block, top_stack->cur_st);
+ }
+ else if (sh->sc == scText && top_stack->blocktype == stFile)
+ {
+ /* End of file. Pop parse stack and ignore. Higher
+ level code deals with this. */
+ ;
+ }
+ else
+ complain (&stEnd_complaint, sh->sc);
+
+ pop_parse_stack (); /* restore previous lexical context */
+ break;
+
+ case stMember: /* member of struct or union */
+ f = &TYPE_FIELDS (top_stack->cur_type)[top_stack->cur_field++];
+ f->name = name;
+ f->bitpos = sh->value;
+ bitsize = 0;
+ f->type = parse_type (cur_fd, ax, sh->index, &bitsize, bigend, name);
+ f->bitsize = bitsize;
+ break;
+
+ case stTypedef: /* type definition */
+ /* Typedefs for forward declarations and opaque structs from alpha cc
+ are handled by cross_ref, skip them. */
+ if (sh->iss == 0)
+ break;
+
+ /* Parse the type or use the pending type. */
+ pend = is_pending_symbol (cur_fdr, ext_sh);
+ if (pend == (struct mips_pending *) NULL)
+ {
+ t = parse_type (cur_fd, ax, sh->index, (int *)NULL, bigend, name);
+ add_pending (cur_fdr, ext_sh, t);
+ }
+ else
+ t = pend->t;
+
+ /* mips cc puts out a typedef with the name of the struct for forward
+ declarations. These should not go into the symbol table and
+ TYPE_NAME should not be set for them.
+ They can't be distinguished from an intentional typedef to
+ the same name however:
+ x.h:
+ struct x { int ix; int jx; };
+ struct xx;
+ x.c:
+ typedef struct x x;
+ struct xx {int ixx; int jxx; };
+ generates a cross referencing stTypedef for x and xx.
+ The user visible effect of this is that the type of a pointer
+ to struct foo sometimes is given as `foo *' instead of `struct foo *'.
+ The problem is fixed with alpha cc. */
+
+ s = new_symbol (name);
+ SYMBOL_NAMESPACE (s) = VAR_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_TYPEDEF;
+ SYMBOL_BLOCK_VALUE (s) = top_stack->cur_block;
+ SYMBOL_TYPE (s) = t;
+ add_symbol (s, top_stack->cur_block);
+
+ /* Incomplete definitions of structs should not get a name. */
+ if (TYPE_NAME (SYMBOL_TYPE (s)) == NULL
+ && (TYPE_NFIELDS (SYMBOL_TYPE (s)) != 0
+ || (TYPE_CODE (SYMBOL_TYPE (s)) != TYPE_CODE_STRUCT
+ && TYPE_CODE (SYMBOL_TYPE (s)) != TYPE_CODE_UNION)))
+ {
+ if (TYPE_CODE (SYMBOL_TYPE (s)) == TYPE_CODE_PTR
+ || TYPE_CODE (SYMBOL_TYPE (s)) == TYPE_CODE_FUNC)
+ {
+ /* If we are giving a name to a type such as "pointer to
+ foo" or "function returning foo", we better not set
+ the TYPE_NAME. If the program contains "typedef char
+ *caddr_t;", we don't want all variables of type char
+ * to print as caddr_t. This is not just a
+ consequence of GDB's type management; CC and GCC (at
+ least through version 2.4) both output variables of
+ either type char * or caddr_t with the type
+ refering to the stTypedef symbol for caddr_t. If a future
+ compiler cleans this up it GDB is not ready for it
+ yet, but if it becomes ready we somehow need to
+ disable this check (without breaking the PCC/GCC2.4
+ case).
+
+ Sigh.
+
+ Fortunately, this check seems not to be necessary
+ for anything except pointers or functions. */
+ }
+ else
+ TYPE_NAME (SYMBOL_TYPE (s)) = SYMBOL_NAME (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:
+ complain (&unknown_mips_symtype_complaint, sh->st);
+ break;
+ }
+
+ return count;
+}
+
+/* Parse the type information provided in the raw AX entries for
+ the symbol SH. Return the bitfield size in BS, in case.
+ We must byte-swap the AX entries before we use them; BIGEND says whether
+ they are big-endian or little-endian (from fh->fBigendian). */
+
+static struct type *
+parse_type (fd, ax, aux_index, bs, bigend, sym_name)
+ int fd;
+ union aux_ext *ax;
+ unsigned int aux_index;
+ int *bs;
+ int bigend;
+ char *sym_name;
+{
+ /* 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 */
+ 0, /* DEC C++: Pointer to member */
+ 0, /* DEC C++: Virtual function table */
+ 0, /* DEC C++: Class (Record) */
+ &builtin_type_long, /* btLong64 */
+ &builtin_type_unsigned_long, /* btULong64 */
+ &builtin_type_long_long, /* btLongLong64 */
+ &builtin_type_unsigned_long_long, /* btULongLong64 */
+ &builtin_type_unsigned_long, /* btAdr64 */
+ &builtin_type_long, /* btInt64 */
+ &builtin_type_unsigned_long, /* btUInt64 */
+ };
+
+ TIR t[1];
+ struct type *tp = 0;
+ enum type_code type_code = TYPE_CODE_UNDEF;
+
+ /* Handle corrupt aux indices. */
+ if (aux_index >= (ecoff_data (cur_bfd)->fdr + fd)->caux)
+ {
+ complain (&index_complaint, sym_name);
+ return builtin_type_int;
+ }
+ ax += aux_index;
+
+ /* Use aux as a type information record, map its basic type. */
+ ecoff_swap_tir_in (bigend, &ax->a_ti, t);
+ if (t->bt >= (sizeof (map_bt) / sizeof (*map_bt)))
+ {
+ complain (&basic_type_complaint, t->bt, sym_name);
+ return builtin_type_int;
+ }
+ if (map_bt[t->bt])
+ {
+ tp = *map_bt[t->bt];
+ }
+ else
+ {
+ tp = NULL;
+ /* Cannot use builtin types -- build our own */
+ switch (t->bt)
+ {
+ case btAdr:
+ tp = lookup_pointer_type (builtin_type_void);
+ break;
+ case btStruct:
+ type_code = TYPE_CODE_STRUCT;
+ break;
+ case btUnion:
+ type_code = TYPE_CODE_UNION;
+ break;
+ case btEnum:
+ type_code = TYPE_CODE_ENUM;
+ break;
+ case btRange:
+ type_code = TYPE_CODE_RANGE;
+ break;
+ case btSet:
+ type_code = TYPE_CODE_SET;
+ break;
+ case btTypedef:
+ /* alpha cc uses this for typedefs. The true type will be
+ obtained by crossreferencing below. */
+ type_code = TYPE_CODE_ERROR;
+ break;
+ default:
+ complain (&basic_type_complaint, t->bt, sym_name);
+ return builtin_type_int;
+ }
+ }
+
+ /* Move on to next aux */
+ ax++;
+
+ if (t->fBitfield)
+ {
+ /* Inhibit core dumps with some cfront generated objects that
+ corrupt the TIR. */
+ if (bs == (int *)NULL)
+ {
+ complain (&bad_fbitfield_complaint, sym_name);
+ return builtin_type_int;
+ }
+ *bs = AUX_GET_WIDTH (bigend, ax);
+ ax++;
+ }
+
+ /* 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 == btStruct ||
+ t->bt == btUnion ||
+ t->bt == btEnum ||
+
+ /* btSet (I think) implies that the name is a tag name, not a typedef
+ name. This apparently is a MIPS extension for C sets. */
+ t->bt == btSet)
+ {
+ char *name;
+
+ /* Try to cross reference this type, build new type on failure. */
+ ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name);
+ if (tp == (struct type *) NULL)
+ tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
+
+ /* Make sure that TYPE_CODE(tp) has an expected type code.
+ Any type may be returned from cross_ref if file indirect entries
+ are corrupted. */
+ if (TYPE_CODE (tp) != TYPE_CODE_STRUCT
+ && TYPE_CODE (tp) != TYPE_CODE_UNION
+ && TYPE_CODE (tp) != TYPE_CODE_ENUM)
+ {
+ complain (&unexpected_type_code_complaint, sym_name);
+ }
+ else
+ {
+
+ /* Usually, TYPE_CODE(tp) is already type_code. The main
+ exception is if we guessed wrong re struct/union/enum.
+ But for struct vs. union a wrong guess is harmless, so
+ don't complain(). */
+ if ((TYPE_CODE (tp) == TYPE_CODE_ENUM
+ && type_code != TYPE_CODE_ENUM)
+ || (TYPE_CODE (tp) != TYPE_CODE_ENUM
+ && type_code == TYPE_CODE_ENUM))
+ {
+ complain (&bad_tag_guess_complaint, sym_name);
+ }
+
+ if (TYPE_CODE (tp) != type_code)
+ {
+ TYPE_CODE (tp) = type_code;
+ }
+
+ /* Do not set the tag name if it is a compiler generated tag name
+ (.Fxx or .xxfake or empty) for unnamed struct/union/enums. */
+ if (name[0] == '.' || name[0] == '\0')
+ TYPE_TAG_NAME (tp) = NULL;
+ else if (TYPE_TAG_NAME (tp) == NULL
+ || !STREQ (TYPE_TAG_NAME (tp), name))
+ TYPE_TAG_NAME (tp) = obsavestring (name, strlen (name),
+ &current_objfile->type_obstack);
+ }
+ }
+
+ /* 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.
+ FIXME: btIndirect cannot happen here as it is handled by the
+ switch t->bt above. And we are not doing any guessing on range types. */
+ if (t->bt == btIndirect ||
+ t->bt == btRange)
+ {
+ char *name;
+
+ /* Try to cross reference this type, build new type on failure. */
+ ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name);
+ if (tp == (struct type *) NULL)
+ tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
+
+ /* Make sure that TYPE_CODE(tp) has an expected type code.
+ Any type may be returned from cross_ref if file indirect entries
+ are corrupted. */
+ if (TYPE_CODE (tp) != TYPE_CODE_RANGE)
+ {
+ complain (&unexpected_type_code_complaint, sym_name);
+ }
+ else
+ {
+ /* Usually, TYPE_CODE(tp) is already type_code. The main
+ exception is if we guessed wrong re struct/union/enum. */
+ if (TYPE_CODE (tp) != type_code)
+ {
+ complain (&bad_tag_guess_complaint, sym_name);
+ TYPE_CODE (tp) = type_code;
+ }
+ if (TYPE_NAME (tp) == NULL || !STREQ (TYPE_NAME (tp), name))
+ TYPE_NAME (tp) = obsavestring (name, strlen (name),
+ &current_objfile->type_obstack);
+ }
+ }
+ if (t->bt == btTypedef)
+ {
+ char *name;
+
+ /* Try to cross reference this type, it should succeed. */
+ ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name);
+ if (tp == (struct type *) NULL)
+ {
+ complain (&unable_to_cross_ref_complaint, sym_name);
+ tp = builtin_type_int;
+ }
+ }
+
+ /* Deal with range types */
+ if (t->bt == btRange)
+ {
+ TYPE_NFIELDS (tp) = 2;
+ TYPE_FIELDS (tp) = ((struct field *)
+ TYPE_ALLOC (tp, 2 * sizeof (struct field)));
+ TYPE_FIELD_NAME (tp, 0) = obsavestring ("Low", strlen ("Low"),
+ &current_objfile->type_obstack);
+ TYPE_FIELD_BITPOS (tp, 0) = AUX_GET_DNLOW (bigend, ax);
+ ax++;
+ TYPE_FIELD_NAME (tp, 1) = obsavestring ("High", strlen ("High"),
+ &current_objfile->type_obstack);
+ TYPE_FIELD_BITPOS (tp, 1) = AUX_GET_DNHIGH (bigend, ax);
+ ax++;
+ }
+
+ /* Parse all the type qualifiers now. If there are more
+ than 6 the game will continue in the next aux */
+
+ while (1)
+ {
+#define PARSE_TQ(tq) \
+ if (t->tq != tqNil) \
+ ax += upgrade_type(fd, &tp, t->tq, ax, bigend, sym_name); \
+ else \
+ break;
+
+ PARSE_TQ (tq0);
+ PARSE_TQ (tq1);
+ PARSE_TQ (tq2);
+ PARSE_TQ (tq3);
+ PARSE_TQ (tq4);
+ PARSE_TQ (tq5);
+#undef PARSE_TQ
+
+ /* mips cc 2.x and gcc never put out continued aux entries. */
+ if (!t->continued)
+ break;
+
+ ecoff_swap_tir_in (bigend, &ax->a_ti, t);
+ ax++;
+ }
+
+ /* Complain for illegal continuations due to corrupt aux entries. */
+ if (t->continued)
+ complain (&bad_continued_complaint, sym_name);
+
+ 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. BIGEND says whether
+ aux symbols are big-endian or little-endian.
+ Returns the number of aux symbols we parsed. */
+
+static int
+upgrade_type (fd, tpp, tq, ax, bigend, sym_name)
+ int fd;
+ struct type **tpp;
+ int tq;
+ union aux_ext *ax;
+ int bigend;
+ char *sym_name;
+{
+ int off;
+ struct type *t;
+
+ /* Used in array processing */
+ int rf, id;
+ FDR *fh;
+ struct type *range;
+ struct type *indx;
+ int lower, upper;
+ RNDXR rndx;
+
+ switch (tq)
+ {
+ case tqPtr:
+ t = lookup_pointer_type (*tpp);
+ *tpp = t;
+ return 0;
+
+ case tqProc:
+ t = lookup_function_type (*tpp);
+ *tpp = t;
+ return 0;
+
+ case tqArray:
+ off = 0;
+
+ /* Determine and record the domain type (type of index) */
+ ecoff_swap_rndx_in (bigend, &ax->a_rndx, &rndx);
+ id = rndx.index;
+ rf = rndx.rfd;
+ if (rf == 0xfff)
+ {
+ ax++;
+ rf = AUX_GET_ISYM (bigend, ax);
+ off++;
+ }
+ fh = get_rfd (fd, rf);
+
+ indx = parse_type (fd,
+ ecoff_data (cur_bfd)->external_aux + fh->iauxBase,
+ id, (int *) NULL, bigend, sym_name);
+
+ /* The bounds type should be an integer type, but might be anything
+ else due to corrupt aux entries. */
+ if (TYPE_CODE (indx) != TYPE_CODE_INT)
+ {
+ complain (&array_index_type_complaint, sym_name);
+ indx = builtin_type_int;
+ }
+
+ /* Get the bounds, and create the array type. */
+ ax++;
+ lower = AUX_GET_DNLOW (bigend, ax);
+ ax++;
+ upper = AUX_GET_DNHIGH (bigend, ax);
+ ax++;
+ rf = AUX_GET_WIDTH (bigend, ax); /* bit size of array element */
+
+ range = create_range_type ((struct type *) NULL, indx,
+ lower, upper);
+
+ t = create_array_type ((struct type *) NULL, *tpp, range);
+
+ /* We used to fill in the supplied array element bitsize
+ here if the TYPE_LENGTH of the target type was zero.
+ This happens for a `pointer to an array of anonymous structs',
+ but in this case the array element bitsize is also zero,
+ so nothing is gained.
+ And we used to check the TYPE_LENGTH of the target type against
+ the supplied array element bitsize.
+ gcc causes a mismatch for `pointer to array of object',
+ since the sdb directives it uses do not have a way of
+ specifying the bitsize, but it does no harm (the
+ TYPE_LENGTH should be correct) and we should be able to
+ ignore the erroneous bitsize from the auxiliary entry safely.
+ dbx seems to ignore it too. */
+
+ *tpp = t;
+ return 4 + off;
+
+ case tqVol:
+ /* Volatile -- currently ignored */
+ return 0;
+
+ case tqConst:
+ /* Const -- currently ignored */
+ return 0;
+
+ default:
+ complain (&unknown_type_qual_complaint, tq);
+ return 0;
+ }
+}
+
+
+/* Parse a procedure descriptor record PR. Note that the procedure is
+ parsed _after_ the local symbols, now we just insert the extra
+ information we need into a MIPS_EFI_SYMBOL_NAME symbol that has
+ already been placed 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. FIRST_OFF is
+ the offset of the first procedure for this FDR; we adjust the
+ address by this amount, but I don't know why. SEARCH_SYMTAB is the symtab
+ to look for the function which contains the MIPS_EFI_SYMBOL_NAME symbol
+ in question, or NULL to use top_stack->cur_block. */
+
+static void parse_procedure PARAMS ((PDR *, struct symtab *, unsigned long));
+
+static void
+parse_procedure (pr, search_symtab, first_off)
+ PDR *pr;
+ struct symtab *search_symtab;
+ unsigned long first_off;
+{
+ struct symbol *s, *i;
+ struct block *b;
+ struct mips_extra_func_info *e;
+ char *sh_name;
+
+ /* Simple rule to find files linked "-x" */
+ if (cur_fdr->rss == -1)
+ {
+ if (pr->isym == -1)
+ {
+ /* Static procedure at address pr->adr. Sigh. */
+ complain (&pdr_static_symbol_complaint, (unsigned long) pr->adr);
+ return;
+ }
+ else
+ {
+ /* external */
+ EXTR she;
+
+ (*ecoff_backend (cur_bfd)->swap_ext_in)
+ (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_ext
+ + pr->isym * ecoff_backend (cur_bfd)->external_ext_size),
+ &she);
+ sh_name = ecoff_data (cur_bfd)->ssext + she.asym.iss;
+ }
+ }
+ else
+ {
+ /* Full symbols */
+ SYMR sh;
+
+ (*ecoff_backend (cur_bfd)->swap_sym_in)
+ (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_sym
+ + ((cur_fdr->isymBase + pr->isym)
+ * ecoff_backend (cur_bfd)->external_sym_size)),
+ &sh);
+ sh_name = ecoff_data (cur_bfd)->ss + cur_fdr->issBase + sh.iss;
+ }
+
+ if (search_symtab != NULL)
+ {
+#if 0
+ /* This loses both in the case mentioned (want a static, find a global),
+ but also if we are looking up a non-mangled name which happens to
+ match the name of a mangled function. */
+ /* We have to save the cur_fdr across the call to lookup_symbol.
+ If the pdr is for a static function and if a global function with
+ the same name exists, lookup_symbol will eventually read in the symtab
+ for the global function and clobber cur_fdr. */
+ FDR *save_cur_fdr = cur_fdr;
+ s = lookup_symbol (sh_name, NULL, VAR_NAMESPACE, 0, NULL);
+ cur_fdr = save_cur_fdr;
+#else
+ s = mylookup_symbol
+ (sh_name,
+ BLOCKVECTOR_BLOCK (BLOCKVECTOR (search_symtab), STATIC_BLOCK),
+ VAR_NAMESPACE,
+ LOC_BLOCK);
+#endif
+ }
+ else
+ s = mylookup_symbol (sh_name, top_stack->cur_block,
+ VAR_NAMESPACE, LOC_BLOCK);
+
+ if (s != 0)
+ {
+ b = SYMBOL_BLOCK_VALUE (s);
+ }
+ else
+ {
+ complain (&pdr_for_nonsymbol_complaint, sh_name);
+#if 1
+ return;
+#else
+/* FIXME -- delete. We can't do symbol allocation now; it's all done. */
+ 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;
+ /* BOUND used to be the end of procedure's text, but the
+ argument is no longer passed in. */
+ BLOCK_END (b) = bound;
+ BLOCK_SUPERBLOCK (b) = top_stack->cur_block;
+ add_block (b, top_stack->cur_st);
+#endif
+ }
+
+ i = mylookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, LOC_CONST);
+
+ if (i)
+ {
+ e = (struct mips_extra_func_info *) SYMBOL_VALUE (i);
+ e->pdr = *pr;
+ e->pdr.isym = (long) s;
+ e->pdr.adr += cur_fdr->adr - first_off;
+
+ /* Correct incorrect setjmp procedure descriptor from the library
+ to make backtrace through setjmp work. */
+ if (e->pdr.pcreg == 0 && STREQ (sh_name, "setjmp"))
+ {
+ complain (&bad_setjmp_pdr_complaint, 0);
+ e->pdr.pcreg = RA_REGNUM;
+ e->pdr.regmask = 0x80000000;
+ e->pdr.regoffset = -4;
+ }
+
+ /* Fake PC_REGNUM for alpha __sigtramp so that read_next_frame_reg
+ will use the saved user pc from the sigcontext. */
+ if (STREQ (sh_name, "__sigtramp"))
+ e->pdr.pcreg = PC_REGNUM;
+ }
+}
+
+/* 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.
+ BIGEND says whether aux entries are big-endian or little-endian.
+
+ This routine clobbers top_stack->cur_block and ->cur_st. */
+
+static void
+parse_external (es, skip_procedures, bigend)
+ EXTR *es;
+ int skip_procedures;
+ int bigend;
+{
+ union aux_ext *ax;
+
+ if (es->ifd != ifdNil)
+ {
+ cur_fd = es->ifd;
+ cur_fdr = ecoff_data (cur_bfd)->fdr + cur_fd;
+ ax = ecoff_data (cur_bfd)->external_aux + cur_fdr->iauxBase;
+ }
+ else
+ {
+ cur_fdr = ecoff_data (cur_bfd)->fdr;
+ ax = 0;
+ }
+
+ /* Reading .o files */
+ if (es->asym.sc == scUndefined || es->asym.sc == scNil)
+ {
+ char *what;
+ switch (es->asym.st)
+ {
+ case stNil:
+ /* These are generated for static symbols in .o files,
+ ignore them. */
+ return;
+ 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++;
+ /* FIXME: Turn this into a complaint? */
+ if (info_verbose)
+ printf_filtered ("Warning: %s `%s' is undefined (in %s)\n",
+ what,
+ ecoff_data (cur_bfd)->ssext + es->asym.iss,
+ fdr_name (cur_fdr));
+ return;
+ }
+
+ switch (es->asym.st)
+ {
+ case stProc:
+ /* If we have full symbols we do not need more */
+ if (skip_procedures)
+ return;
+ if (mylookup_symbol (ecoff_data (cur_bfd)->ssext + 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, (char *) NULL, bigend);
+ 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 void
+parse_lines (fh, pr, lt, maxlines)
+ FDR *fh;
+ PDR *pr;
+ struct linetable *lt;
+ int maxlines;
+{
+ unsigned char *base;
+ int j, k;
+ int delta, count, lineno = 0;
+ unsigned long first_off = pr->adr;
+
+ if (fh->cbLine == 0)
+ return;
+
+ base = ecoff_data (cur_bfd)->line + fh->cbLineOffset;
+
+ /* Scan by procedure descriptors */
+ k = 0;
+ for (j = 0; j < fh->cpd; j++, pr++)
+ {
+ long l;
+ unsigned long adr;
+ unsigned char *halt;
+
+ /* No code for this one */
+ if (pr->iline == ilineNil ||
+ pr->lnLow == -1 || pr->lnHigh == -1)
+ continue;
+
+ /* Determine start and end address of compressed line bytes for
+ this procedure. */
+ base = ecoff_data (cur_bfd)->line + fh->cbLineOffset;
+ if (j != (fh->cpd - 1))
+ halt = base + pr[1].cbLineOffset;
+ else
+ halt = base + fh->cbLine;
+ base += pr->cbLineOffset;
+
+ adr = fh->adr + pr->adr - first_off;
+ l = adr >> 2; /* in words */
+ for (lineno = pr->lnLow; base < halt; )
+ {
+ count = *base & 0x0f;
+ delta = *base++ >> 4;
+ if (delta >= 8)
+ delta -= 16;
+ if (delta == -8)
+ {
+ delta = (base[0] << 8) | base[1];
+ if (delta >= 0x8000)
+ delta -= 0x10000;
+ base += 2;
+ }
+ lineno += delta; /* first delta is 0 */
+
+ /* Complain if the line table overflows. Could happen
+ with corrupt binaries. */
+ if (lt->nitems >= maxlines)
+ {
+ complain (&bad_linetable_guess_complaint, fdr_name (fh));
+ break;
+ }
+ k = add_line (lt, lineno, l, k);
+ l += count + 1;
+ }
+ }
+}
+
+/* Master parsing procedure for first-pass reading of file symbols
+ into a partial_symtab. */
+
+static void
+parse_partial_symbols (objfile, section_offsets)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (cur_bfd);
+ const bfd_size_type external_sym_size = backend->external_sym_size;
+ const bfd_size_type external_rfd_size = backend->external_rfd_size;
+ const bfd_size_type external_ext_size = backend->external_ext_size;
+ void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *))
+ = backend->swap_ext_in;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = backend->swap_sym_in;
+ void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *))
+ = backend->swap_rfd_in;
+ int f_idx, s_idx;
+ HDRR *hdr = &ecoff_data (cur_bfd)->symbolic_header;
+ /* Running pointers */
+ FDR *fh;
+ char *ext_out;
+ char *ext_out_end;
+ EXTR *ext_block;
+ register EXTR *ext_in;
+ EXTR *ext_in_end;
+ SYMR sh;
+ struct partial_symtab *pst;
+
+ int past_first_source_file = 0;
+
+ /* List of current psymtab's include files */
+ char **psymtab_include_list;
+ int includes_allocated;
+ int includes_used;
+ EXTR *extern_tab;
+ struct pst_map *fdr_to_pst;
+ /* Index within current psymtab dependency list */
+ struct partial_symtab **dependency_list;
+ int dependencies_used, dependencies_allocated;
+ struct cleanup *old_chain;
+ char *name;
+ enum language prev_language;
+
+ extern_tab = (EXTR *) obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (EXTR) * hdr->iextMax);
+
+ includes_allocated = 30;
+ includes_used = 0;
+ psymtab_include_list = (char **) alloca (includes_allocated *
+ sizeof (char *));
+ next_symbol_text_func = mips_next_symbol_text;
+
+ dependencies_allocated = 30;
+ dependencies_used = 0;
+ dependency_list =
+ (struct partial_symtab **) alloca (dependencies_allocated *
+ sizeof (struct partial_symtab *));
+
+ last_source_file = NULL;
+
+ /*
+ * Big plan:
+ *
+ * Only parse the Local and 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)
+ */
+
+ 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);
+ old_chain = make_cleanup (free, fdr_to_pst);
+ fdr_to_pst++;
+ {
+ struct partial_symtab *pst = new_psymtab ("", objfile);
+ fdr_to_pst[-1].pst = pst;
+ FDR_IDX (pst) = -1;
+ }
+
+ /* Allocate the global pending list. */
+ ECOFF_PENDING_LIST (objfile) =
+ ((struct mips_pending **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ hdr->ifdMax * sizeof (struct mips_pending *)));
+ memset ((PTR) ECOFF_PENDING_LIST (objfile), 0,
+ hdr->ifdMax * sizeof (struct mips_pending *));
+
+ /* Pass 0 over external syms: swap them in. */
+ ext_block = (EXTR *) xmalloc (hdr->iextMax * sizeof (EXTR));
+ make_cleanup (free, ext_block);
+
+ ext_out = (char *) ecoff_data (cur_bfd)->external_ext;
+ ext_out_end = ext_out + hdr->iextMax * external_ext_size;
+ ext_in = ext_block;
+ for (; ext_out < ext_out_end; ext_out += external_ext_size, ext_in++)
+ (*swap_ext_in) (cur_bfd, ext_out, ext_in);
+
+ /* Pass 1 over external syms: Presize and partition the list */
+ ext_in = ext_block;
+ ext_in_end = ext_in + hdr->iextMax;
+ for (; ext_in < ext_in_end; ext_in++)
+ fdr_to_pst[ext_in->ifd].n_globals++;
+
+ /* Pass 1.5 over files: partition out global symbol space */
+ s_idx = 0;
+ for (f_idx = -1; f_idx < hdr->ifdMax; f_idx++)
+ {
+ fdr_to_pst[f_idx].globals_offset = s_idx;
+ s_idx += fdr_to_pst[f_idx].n_globals;
+ fdr_to_pst[f_idx].n_globals = 0;
+ }
+
+ /* Pass 2 over external syms: fill in external symbols */
+ ext_in = ext_block;
+ ext_in_end = ext_in + hdr->iextMax;
+ for (; ext_in < ext_in_end; ext_in++)
+ {
+ enum minimal_symbol_type ms_type = mst_text;
+
+ extern_tab[fdr_to_pst[ext_in->ifd].globals_offset
+ + fdr_to_pst[ext_in->ifd].n_globals++] = *ext_in;
+
+ if (ext_in->asym.sc == scUndefined || ext_in->asym.sc == scNil)
+ continue;
+
+ name = ecoff_data (cur_bfd)->ssext + ext_in->asym.iss;
+ switch (ext_in->asym.st)
+ {
+ case stProc:
+ break;
+ case stStaticProc:
+ ms_type = mst_file_text;
+ break;
+ case stGlobal:
+ if (ext_in->asym.sc == scData
+ || ext_in->asym.sc == scSData
+ || ext_in->asym.sc == scRData)
+ ms_type = mst_data;
+ else
+ ms_type = mst_bss;
+ break;
+ case stLabel:
+ if (ext_in->asym.sc == scAbs)
+ ms_type = mst_abs;
+ else if (ext_in->asym.sc == scText)
+ ms_type = mst_text;
+ else if (ext_in->asym.sc == scData
+ || ext_in->asym.sc == scSData
+ || ext_in->asym.sc == scRData)
+ ms_type = mst_data;
+ else
+ ms_type = mst_bss;
+ break;
+ case stLocal:
+ /* The alpha has the section start addresses in stLocal symbols
+ whose name starts with a `.'. Skip those but complain for all
+ other stLocal symbols. */
+ if (name[0] == '.')
+ continue;
+ /* Fall through. */
+ default:
+ ms_type = mst_unknown;
+ complain (&unknown_ext_complaint, name);
+ }
+ prim_record_minimal_symbol (name, ext_in->asym.value, ms_type);
+ }
+
+ /* Pass 3 over files, over local syms: fill in static symbols */
+ for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++)
+ {
+ struct partial_symtab *save_pst;
+ EXTR *ext_ptr;
+
+ cur_fdr = fh = ecoff_data (cur_bfd)->fdr + f_idx;
+
+ if (fh->csym == 0)
+ {
+ fdr_to_pst[f_idx].pst = NULL;
+ continue;
+ }
+ pst = start_psymtab_common (objfile, section_offsets,
+ fdr_name (fh),
+ fh->cpd ? fh->adr : 0,
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ pst->read_symtab_private = ((char *)
+ obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct symloc)));
+ memset ((PTR) pst->read_symtab_private, 0, sizeof (struct symloc));
+
+ save_pst = pst;
+ FDR_IDX (pst) = f_idx;
+ CUR_BFD (pst) = cur_bfd;
+
+ /* The way to turn this into a symtab is to call... */
+ pst->read_symtab = mipscoff_psymtab_to_symtab;
+
+ /* Set up language for the pst.
+ The language from the FDR is used if it is unambigious (e.g. cfront
+ with native cc and g++ will set the language to C).
+ Otherwise we have to deduce the language from the filename.
+ Native ecoff has every header file in a separate FDR, so
+ deduce_language_from_filename will return language_unknown for
+ a header file, which is not what we want.
+ But the FDRs for the header files are after the FDR for the source
+ file, so we can assign the language of the source file to the
+ following header files. Then we save the language in the private
+ pst data so that we can reuse it when building symtabs. */
+ prev_language = psymtab_language;
+
+ switch (fh->lang)
+ {
+ case langCplusplusV2:
+ psymtab_language = language_cplus;
+ break;
+ default:
+ psymtab_language = deduce_language_from_filename (fdr_name (fh));
+ break;
+ }
+ if (psymtab_language == language_unknown)
+ psymtab_language = prev_language;
+ PST_PRIVATE (pst)->pst_language = psymtab_language;
+
+ pst->texthigh = pst->textlow;
+
+ /* For stabs-in-ecoff files, the second symbol must be @stab.
+ This symbol is emitted by mips-tfile to signal that the
+ current object file uses encapsulated stabs instead of mips
+ ecoff for local symbols. (It is the second symbol because
+ the first symbol is the stFile used to signal the start of a
+ file). */
+ processing_gcc_compilation = 0;
+ if (fh->csym >= 2)
+ {
+ (*swap_sym_in) (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_sym
+ + (fh->isymBase + 1) * external_sym_size),
+ &sh);
+ if (STREQ (ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss,
+ stabs_symbol))
+ processing_gcc_compilation = 2;
+ }
+
+ if (processing_gcc_compilation != 0)
+ {
+ for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++)
+ {
+ int type_code;
+ char *namestring;
+
+ (*swap_sym_in) (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_sym
+ + (fh->isymBase + cur_sdx) * external_sym_size),
+ &sh);
+ type_code = ECOFF_UNMARK_STAB (sh.index);
+ if (!ECOFF_IS_STAB (&sh))
+ {
+ if (sh.st == stProc || sh.st == stStaticProc)
+ {
+ long procaddr = sh.value;
+ long isym;
+
+
+ isym = AUX_GET_ISYM (fh->fBigendian,
+ (ecoff_data (cur_bfd)->external_aux
+ + fh->iauxBase
+ + sh.index));
+ (*swap_sym_in) (cur_bfd,
+ (((char *)
+ ecoff_data (cur_bfd)->external_sym)
+ + ((fh->isymBase + isym - 1)
+ * external_sym_size)),
+ &sh);
+ if (sh.st == stEnd)
+ {
+ long high = procaddr + sh.value;
+ if (high > pst->texthigh)
+ pst->texthigh = high;
+ }
+ }
+ continue;
+ }
+#define SET_NAMESTRING() \
+ namestring = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss
+#define CUR_SYMBOL_TYPE type_code
+#define CUR_SYMBOL_VALUE sh.value
+#define START_PSYMTAB(ofile,secoff,fname,low,symoff,global_syms,static_syms)\
+ pst = save_pst
+#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps) (void)0
+#define HANDLE_RBRAC(val) \
+ if ((val) > save_pst->texthigh) save_pst->texthigh = (val);
+#include "partial-stab.h"
+ }
+ }
+ else
+ {
+ for (cur_sdx = 0; cur_sdx < fh->csym;)
+ {
+ char *name;
+ enum address_class class;
+
+ (*swap_sym_in) (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_sym
+ + ((fh->isymBase + cur_sdx)
+ * external_sym_size)),
+ &sh);
+
+ if (ECOFF_IS_STAB (&sh))
+ {
+ cur_sdx++;
+ continue;
+ }
+
+ /* Non absolute static symbols go into the minimal table. */
+ if (sh.sc == scUndefined || sh.sc == scNil
+ || (sh.index == indexNil
+ && (sh.st != stStatic || sh.sc == scAbs)))
+ {
+ /* FIXME, premature? */
+ cur_sdx++;
+ continue;
+ }
+
+ name = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss;
+
+ switch (sh.st)
+ {
+ long high;
+ long procaddr;
+ int new_sdx;
+
+ case stStaticProc: /* Function */
+ /* I believe this is used only for file-local functions.
+ The comment in symconst.h ("load time only static procs")
+ isn't particularly clear on this point. */
+ prim_record_minimal_symbol (name, sh.value, mst_file_text);
+ /* FALLTHROUGH */
+
+ case stProc: /* Asm labels apparently */
+ ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ objfile->static_psymbols, sh.value,
+ psymtab_language, objfile);
+ /* Skip over procedure to next one. */
+ if (sh.index >= hdr->iauxMax)
+ {
+ /* Should not happen, but does when cross-compiling
+ with the MIPS compiler. FIXME -- pull later. */
+ complain (&index_complaint, name);
+ new_sdx = cur_sdx + 1; /* Don't skip at all */
+ }
+ else
+ new_sdx = AUX_GET_ISYM (fh->fBigendian,
+ (ecoff_data (cur_bfd)->external_aux
+ + fh->iauxBase
+ + sh.index));
+ procaddr = sh.value;
+
+ if (new_sdx <= cur_sdx)
+ {
+ /* This should not happen either... FIXME. */
+ complain (&aux_index_complaint, name);
+ new_sdx = cur_sdx + 1; /* Don't skip backward */
+ }
+
+ cur_sdx = new_sdx;
+ (*swap_sym_in) (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_sym
+ + ((fh->isymBase + cur_sdx - 1)
+ * external_sym_size)),
+ &sh);
+ if (sh.st != stEnd)
+ continue;
+ high = procaddr + sh.value;
+ if (high > pst->texthigh)
+ pst->texthigh = high;
+ continue;
+
+ case stStatic: /* Variable */
+ if (sh.sc == scData || sh.sc == scSData || sh.sc == scRData)
+ prim_record_minimal_symbol (name, sh.value, mst_file_data);
+ else
+ prim_record_minimal_symbol (name, sh.value, mst_file_bss);
+ class = LOC_STATIC;
+ break;
+
+ case stTypedef:/* Typedef */
+ class = LOC_TYPEDEF;
+ break;
+
+ case stConstant: /* Constant decl */
+ class = LOC_CONST;
+ break;
+
+ case stUnion:
+ case stStruct:
+ case stEnum:
+ case stBlock: /* { }, str, un, enum*/
+ if (sh.sc == scInfo || sh.sc == scCommon)
+ {
+ ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ objfile->static_psymbols,
+ sh.value,
+ psymtab_language, objfile);
+ }
+ /* Skip over the block */
+ new_sdx = sh.index;
+ if (new_sdx <= cur_sdx)
+ {
+ /* This happens with the Ultrix kernel. */
+ complain (&block_index_complaint, name);
+ new_sdx = cur_sdx + 1; /* Don't skip backward */
+ }
+ cur_sdx = new_sdx;
+ continue;
+
+ case stFile: /* File headers */
+ case stLabel: /* Labels */
+ case stEnd: /* Ends of files */
+ goto skip;
+
+ case stLocal: /* Local variables */
+ /* Normally these are skipped because we skip over
+ all blocks we see. However, these can occur
+ as visible symbols in a .h file that contains code. */
+ goto skip;
+
+ default:
+ /* Both complaints are valid: one gives symbol name,
+ the other the offending symbol type. */
+ complain (&unknown_sym_complaint, name);
+ complain (&unknown_st_complaint, sh.st);
+ cur_sdx++;
+ continue;
+ }
+ /* Use this gdb symbol */
+ ADD_PSYMBOL_TO_LIST (name, strlen (name),
+ VAR_NAMESPACE, class,
+ objfile->static_psymbols, sh.value,
+ psymtab_language, objfile);
+ skip:
+ cur_sdx++; /* Go to next file symbol */
+ }
+
+ /* Now do enter the external symbols. */
+ ext_ptr = &extern_tab[fdr_to_pst[f_idx].globals_offset];
+ cur_sdx = fdr_to_pst[f_idx].n_globals;
+ PST_PRIVATE (save_pst)->extern_count = cur_sdx;
+ PST_PRIVATE (save_pst)->extern_tab = ext_ptr;
+ for (; --cur_sdx >= 0; ext_ptr++)
+ {
+ enum address_class class;
+ SYMR *psh;
+ char *name;
+
+ if (ext_ptr->ifd != f_idx)
+ abort ();
+ psh = &ext_ptr->asym;
+
+ /* Do not add undefined symbols to the partial symbol table. */
+ if (psh->sc == scUndefined || psh->sc == scNil)
+ continue;
+
+ switch (psh->st)
+ {
+ case stNil:
+ /* These are generated for static symbols in .o files,
+ ignore them. */
+ continue;
+ case stProc:
+ case stStaticProc:
+ class = LOC_BLOCK;
+ break;
+ case stLabel:
+ class = LOC_LABEL;
+ break;
+ default:
+ complain (&unknown_ext_complaint,
+ ecoff_data (cur_bfd)->ssext + psh->iss);
+ /* Fall through, pretend it's global. */
+ case stGlobal:
+ class = LOC_STATIC;
+ break;
+ }
+ name = ecoff_data (cur_bfd)->ssext + psh->iss;
+ ADD_PSYMBOL_ADDR_TO_LIST (name, strlen (name),
+ VAR_NAMESPACE, class,
+ objfile->global_psymbols, (CORE_ADDR) psh->value,
+ psymtab_language, objfile);
+ }
+ }
+
+ /* Link pst to FDR. end_psymtab returns NULL if the psymtab was
+ empty and put on the free list. */
+ fdr_to_pst[f_idx].pst = end_psymtab (save_pst,
+ psymtab_include_list, includes_used,
+ -1, save_pst->texthigh,
+ dependency_list, dependencies_used);
+ if (objfile->ei.entry_point >= save_pst->textlow &&
+ objfile->ei.entry_point < save_pst->texthigh)
+ {
+ objfile->ei.entry_file_lowpc = save_pst->textlow;
+ objfile->ei.entry_file_highpc = save_pst->texthigh;
+ }
+ }
+
+ /* Now scan the FDRs for dependencies */
+ for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++)
+ {
+ fh = f_idx + ecoff_data (cur_bfd)->fdr;
+ pst = fdr_to_pst[f_idx].pst;
+
+ if (pst == (struct partial_symtab *)NULL)
+ continue;
+
+ /* This should catch stabs-in-ecoff. */
+ if (fh->crfd <= 1)
+ continue;
+
+ /* Skip the first file indirect entry as it is a self dependency
+ for source files or a reverse .h -> .c dependency for header files. */
+ pst->number_of_dependencies = 0;
+ pst->dependencies =
+ ((struct partial_symtab **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ ((fh->crfd - 1)
+ * sizeof (struct partial_symtab *))));
+ for (s_idx = 1; s_idx < fh->crfd; s_idx++)
+ {
+ RFDT rh;
+
+ (*swap_rfd_in) (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_rfd
+ + (fh->rfdBase + s_idx) * external_rfd_size),
+ &rh);
+ if (rh < 0 || rh >= hdr->ifdMax)
+ {
+ complain (&bad_file_number_complaint, rh);
+ continue;
+ }
+
+ /* Skip self dependencies of header files. */
+ if (rh == f_idx)
+ continue;
+
+ /* Do not add to dependeny list if psymtab was empty. */
+ if (fdr_to_pst[rh].pst == (struct partial_symtab *)NULL)
+ continue;
+ pst->dependencies[pst->number_of_dependencies++] = fdr_to_pst[rh].pst;
+ }
+ }
+ do_cleanups (old_chain);
+}
+
+
+static char *
+mips_next_symbol_text ()
+{
+ SYMR sh;
+
+ cur_sdx++;
+ (*ecoff_backend (cur_bfd)->swap_sym_in)
+ (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_sym
+ + ((cur_fdr->isymBase + cur_sdx)
+ * ecoff_backend (cur_bfd)->external_sym_size)),
+ &sh);
+ return ecoff_data (cur_bfd)->ss + cur_fdr->issBase + sh.iss;
+}
+
+/* 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. The argument FILENAME is
+ only passed so we can see in debug stack traces what file
+ is being read.
+
+ This function has a split personality, based on whether the
+ symbol table contains ordinary ecoff symbols, or stabs-in-ecoff.
+ The flow of control and even the memory allocation differs. FIXME. */
+
+static void
+psymtab_to_symtab_1 (pst, filename)
+ struct partial_symtab *pst;
+ char *filename;
+{
+ const bfd_size_type external_sym_size
+ = ecoff_backend (cur_bfd)->external_sym_size;
+ const bfd_size_type external_pdr_size
+ = ecoff_backend (cur_bfd)->external_pdr_size;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = ecoff_backend (cur_bfd)->swap_sym_in;
+ void (* const swap_pdr_in) PARAMS ((bfd *, PTR, PDR *))
+ = ecoff_backend (cur_bfd)->swap_pdr_in;
+ int i;
+ struct symtab *st;
+ FDR *fh;
+ struct linetable *lines;
+
+ if (pst->readin)
+ return;
+ pst->readin = 1;
+
+ /* Read in all partial symbtabs on which this one is dependent.
+ NOTE that we do have circular dependencies, sigh. We solved
+ that by setting pst->readin before this point. */
+
+ for (i = 0; i < pst->number_of_dependencies; i++)
+ if (!pst->dependencies[i]->readin)
+ {
+ /* Inform about additional files 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);
+ }
+ /* We only pass the filename for debug purposes */
+ psymtab_to_symtab_1 (pst->dependencies[i],
+ pst->dependencies[i]->filename);
+ }
+
+ /* Do nothing if this is a dummy psymtab. */
+
+ if (pst->n_global_syms == 0 && pst->n_static_syms == 0
+ && pst->textlow == 0 && pst->texthigh == 0)
+ return;
+
+ /* Now read the symbols for this symtab */
+
+ cur_bfd = CUR_BFD (pst);
+ current_objfile = pst->objfile;
+ cur_fd = FDR_IDX (pst);
+ fh = (cur_fd == -1) ? (FDR *) NULL : ecoff_data (cur_bfd)->fdr + cur_fd;
+ cur_fdr = fh;
+
+ /* See comment in parse_partial_symbols about the @stabs sentinel. */
+ processing_gcc_compilation = 0;
+ if (fh != (FDR *) NULL && fh->csym >= 2)
+ {
+ SYMR sh;
+
+ (*swap_sym_in) (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_sym
+ + (fh->isymBase + 1) * external_sym_size),
+ &sh);
+ if (STREQ (ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss,
+ stabs_symbol))
+ {
+ /* We indicate that this is a GCC compilation so that certain
+ features will be enabled in stabsread/dbxread. */
+ processing_gcc_compilation = 2;
+ }
+ }
+
+ if (processing_gcc_compilation != 0)
+ {
+ char *pdr_ptr;
+ char *pdr_end;
+ int first_pdr;
+ unsigned long first_off = 0;
+
+ /* This symbol table contains stabs-in-ecoff entries. */
+
+ /* Parse local symbols first */
+
+ if (fh->csym <= 2) /* FIXME, this blows psymtab->symtab ptr */
+ {
+ current_objfile = NULL;
+ return;
+ }
+ for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++)
+ {
+ SYMR sh;
+ char *name;
+ CORE_ADDR valu;
+
+ (*swap_sym_in) (cur_bfd,
+ ((char *) ecoff_data (cur_bfd)->external_sym
+ + (fh->isymBase + cur_sdx) * external_sym_size),
+ &sh);
+ name = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss;
+ valu = sh.value;
+ if (ECOFF_IS_STAB (&sh))
+ {
+ int type_code = ECOFF_UNMARK_STAB (sh.index);
+ process_one_symbol (type_code, 0, valu, name,
+ pst->section_offsets, pst->objfile);
+ if (type_code == N_FUN)
+ {
+ /* Make up special symbol to contain
+ procedure specific info */
+ struct mips_extra_func_info *e =
+ ((struct mips_extra_func_info *)
+ obstack_alloc (&current_objfile->symbol_obstack,
+ sizeof (struct mips_extra_func_info)));
+ struct symbol *s = new_symbol (MIPS_EFI_SYMBOL_NAME);
+ SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_CONST;
+ SYMBOL_TYPE (s) = builtin_type_void;
+ SYMBOL_VALUE (s) = (long) e;
+ add_symbol_to_list (s, &local_symbols);
+ }
+ }
+ else if (sh.st == stLabel && sh.index != indexNil)
+ {
+ /* Handle encoded stab line number. */
+ record_line (current_subfile, sh.index, valu);
+ }
+ else if (sh.st == stProc || sh.st == stStaticProc || sh.st == stEnd)
+ /* These are generated by gcc-2.x, do not complain */
+ ;
+ else
+ complain (&stab_unknown_complaint, name);
+ }
+ st = end_symtab (pst->texthigh, 0, 0, pst->objfile, SECT_OFF_TEXT);
+ end_stabs ();
+
+ /* Sort the symbol table now, we are done adding symbols to it.
+ We must do this before parse_procedure calls lookup_symbol. */
+ sort_symtab_syms (st);
+
+ /* This may not be necessary for stabs symtabs. FIXME. */
+ sort_blocks (st);
+
+ /* Fill in procedure info next. */
+ first_pdr = 1;
+ pdr_ptr = ((char *) ecoff_data (cur_bfd)->external_pdr
+ + fh->ipdFirst * external_pdr_size);
+ pdr_end = pdr_ptr + fh->cpd * external_pdr_size;
+ for (; pdr_ptr < pdr_end; pdr_ptr += external_pdr_size)
+ {
+ PDR pr;
+
+ (*swap_pdr_in) (cur_bfd, pdr_ptr, &pr);
+ if (first_pdr)
+ {
+ first_off = pr.adr;
+ first_pdr = 0;
+ }
+ parse_procedure (&pr, st, first_off);
+ }
+ }
+ else
+ {
+ /* This symbol table contains ordinary ecoff entries. */
+
+ /* FIXME: doesn't use pst->section_offsets. */
+
+ int f_max;
+ int maxlines;
+ EXTR *ext_ptr;
+
+ /* How many symbols will we need */
+ /* FIXME, this does not count enum values. */
+ f_max = pst->n_global_syms + pst->n_static_syms;
+ if (fh == 0)
+ {
+ maxlines = 0;
+ st = new_symtab ("unknown", f_max, 0, pst->objfile);
+ }
+ else
+ {
+ f_max += fh->csym + fh->cpd;
+ maxlines = 2 * fh->cline;
+ st = new_symtab (pst->filename, 2 * f_max, maxlines, pst->objfile);
+
+ /* The proper language was already determined when building
+ the psymtab, use it. */
+ st->language = PST_PRIVATE (pst)->pst_language;
+ }
+
+ psymtab_language = st->language;
+
+ lines = LINETABLE (st);
+
+ /* Get a new lexical context */
+
+ push_parse_stack ();
+ top_stack->cur_st = st;
+ top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (st),
+ STATIC_BLOCK);
+ BLOCK_START (top_stack->cur_block) = fh ? fh->adr : 0;
+ BLOCK_END (top_stack->cur_block) = 0;
+ top_stack->blocktype = stFile;
+ top_stack->maxsyms = 2 * f_max;
+ top_stack->cur_type = 0;
+ top_stack->procadr = 0;
+ top_stack->numargs = 0;
+
+ if (fh)
+ {
+ char *sym_ptr;
+ char *sym_end;
+
+ /* Parse local symbols first */
+ sym_ptr = ((char *) ecoff_data (cur_bfd)->external_sym
+ + fh->isymBase * external_sym_size);
+ sym_end = sym_ptr + fh->csym * external_sym_size;
+ while (sym_ptr < sym_end)
+ {
+ SYMR sh;
+ int c;
+
+ (*swap_sym_in) (cur_bfd, sym_ptr, &sh);
+ c = parse_symbol (&sh,
+ (ecoff_data (cur_bfd)->external_aux
+ + fh->iauxBase),
+ sym_ptr, fh->fBigendian);
+ sym_ptr += c * external_sym_size;
+ }
+
+ /* Linenumbers. At the end, check if we can save memory.
+ parse_lines has to look ahead an arbitrary number of PDR
+ structures, so we swap them all first. */
+ if (fh->cpd > 0)
+ {
+ PDR *pr_block;
+ struct cleanup *old_chain;
+ char *pdr_ptr;
+ char *pdr_end;
+ PDR *pdr_in;
+ PDR *pdr_in_end;
+
+ pr_block = (PDR *) xmalloc (fh->cpd * sizeof (PDR));
+
+ old_chain = make_cleanup (free, pr_block);
+
+ pdr_ptr = ((char *) ecoff_data (cur_bfd)->external_pdr
+ + fh->ipdFirst * external_pdr_size);
+ pdr_end = pdr_ptr + fh->cpd * external_pdr_size;
+ pdr_in = pr_block;
+ for (;
+ pdr_ptr < pdr_end;
+ pdr_ptr += external_pdr_size, pdr_in++)
+ (*swap_pdr_in) (cur_bfd, pdr_ptr, pdr_in);
+
+ parse_lines (fh, pr_block, lines, maxlines);
+ if (lines->nitems < fh->cline)
+ lines = shrink_linetable (lines);
+
+ /* Fill in procedure info next. */
+ pdr_in = pr_block;
+ pdr_in_end = pdr_in + fh->cpd;
+ for (; pdr_in < pdr_in_end; pdr_in++)
+ parse_procedure (pdr_in, 0, pr_block->adr);
+
+ do_cleanups (old_chain);
+ }
+ }
+
+ LINETABLE (st) = lines;
+
+ /* .. and our share of externals.
+ XXX use the global list to speed up things here. how?
+ FIXME, Maybe quit once we have found the right number of ext's? */
+ top_stack->cur_st = st;
+ top_stack->cur_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (top_stack->cur_st),
+ GLOBAL_BLOCK);
+ top_stack->blocktype = stFile;
+ top_stack->maxsyms = (ecoff_data (cur_bfd)->symbolic_header.isymMax
+ + ecoff_data (cur_bfd)->symbolic_header.ipdMax
+ + ecoff_data (cur_bfd)->symbolic_header.iextMax);
+
+ ext_ptr = PST_PRIVATE (pst)->extern_tab;
+ for (i = PST_PRIVATE (pst)->extern_count; --i >= 0; ext_ptr++)
+ parse_external (ext_ptr, 1, fh->fBigendian);
+
+ /* If there are undefined symbols, tell the user.
+ The alpha has an undefined symbol for every symbol that is
+ from a shared library, so tell the user only if verbose is on. */
+ if (info_verbose && 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);
+
+ sort_blocks (st);
+ }
+
+ /* Now link the psymtab and the symtab. */
+ pst->symtab = st;
+
+ current_objfile = NULL;
+}
+
+/* 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.
+ BIGEND says whether aux symbols are big-endian or not (from fh->fBigendian).
+ Return value says how many aux symbols we ate. */
+
+static int
+cross_ref (fd, ax, tpp, type_code, pname, bigend, sym_name)
+ int fd;
+ union aux_ext *ax;
+ struct type **tpp;
+ enum type_code type_code; /* Use to alloc new type if none is found. */
+ char **pname;
+ int bigend;
+ char *sym_name;
+{
+ RNDXR rn[1];
+ unsigned int rf;
+ int result = 1;
+ FDR *fh;
+ char *esh;
+ SYMR sh;
+ int xref_fd;
+ struct mips_pending *pend;
+
+ *tpp = (struct type *)NULL;
+
+ ecoff_swap_rndx_in (bigend, &ax->a_rndx, rn);
+
+ /* Escape index means 'the next one' */
+ if (rn->rfd == 0xfff)
+ {
+ result++;
+ rf = AUX_GET_ISYM (bigend, ax + 1);
+ }
+ else
+ {
+ rf = rn->rfd;
+ }
+
+ /* mips cc uses a rf of -1 for opaque struct definitions.
+ Set TYPE_FLAG_STUB for these types so that check_stub_type will
+ resolve them if the struct gets defined in another compilation unit. */
+ if (rf == -1)
+ {
+ *pname = "<undefined>";
+ *tpp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
+ TYPE_FLAGS (*tpp) |= TYPE_FLAG_STUB;
+ return result;
+ }
+
+ /* mips cc uses an escaped rn->index of 0 for struct return types
+ of procedures that were compiled without -g. These will always remain
+ undefined. */
+ if (rn->rfd == 0xfff && rn->index == 0)
+ {
+ *pname = "<undefined>";
+ return result;
+ }
+
+ /* Find the relative file descriptor and the symbol in it. */
+ fh = get_rfd (fd, rf);
+ xref_fd = fh - ecoff_data (cur_bfd)->fdr;
+
+ if (rn->index >= fh->csym)
+ {
+ /* File indirect entry is corrupt. */
+ *pname = "<illegal>";
+ complain (&bad_rfd_entry_complaint,
+ sym_name, xref_fd, rn->index);
+ return result;
+ }
+
+ /* If we have processed this symbol then we left a forwarding
+ pointer to the type in the pending list. If not, we`ll put
+ it in a list of pending types, to be processed later when
+ the file will be. In any event, we collect the name for the
+ type here. */
+
+ esh = ((char *) ecoff_data (cur_bfd)->external_sym
+ + ((fh->isymBase + rn->index)
+ * ecoff_backend (cur_bfd)->external_sym_size));
+ (*ecoff_backend (cur_bfd)->swap_sym_in) (cur_bfd, esh, &sh);
+
+ /* Make sure that this type of cross reference can be handled. */
+ if (sh.sc != scInfo
+ || (sh.st != stBlock && sh.st != stTypedef
+ && sh.st != stStruct && sh.st != stUnion
+ && sh.st != stEnum))
+ {
+ /* File indirect entry is corrupt. */
+ *pname = "<illegal>";
+ complain (&bad_rfd_entry_complaint,
+ sym_name, xref_fd, rn->index);
+ return result;
+ }
+
+ *pname = ecoff_data (cur_bfd)->ss + fh->issBase + sh.iss;
+
+ pend = is_pending_symbol (fh, esh);
+ if (pend)
+ *tpp = pend->t;
+ else
+ {
+ /* We have not yet seen this type. */
+
+ if (sh.iss == 0 && sh.st == stTypedef)
+ {
+ TIR tir;
+
+ /* alpha cc puts out a stTypedef with a sh.iss of zero for
+ two cases:
+ a) forward declarations of structs/unions/enums which are not
+ defined in this compilation unit.
+ For these the type will be void. This is a bad design decision
+ as cross referencing across compilation units is impossible
+ due to the missing name.
+ b) forward declarations of structs/unions/enums which are defined
+ later in this file or in another file in the same compilation
+ unit. Simply cross reference those again to get the
+ true type.
+ The forward references are not entered in the pending list and
+ in the symbol table. */
+
+ ecoff_swap_tir_in (bigend,
+ &(ecoff_data (cur_bfd)->external_aux
+ + fh->iauxBase + sh.index)->a_ti,
+ &tir);
+ if (tir.tq0 != tqNil)
+ complain (&illegal_forward_tq0_complaint, sym_name);
+ switch (tir.bt)
+ {
+ case btVoid:
+ *tpp = init_type (type_code, 0, 0, (char *) NULL,
+ current_objfile);
+ *pname = "<undefined>";
+ break;
+
+ case btStruct:
+ case btUnion:
+ case btEnum:
+ cross_ref (xref_fd,
+ (ecoff_data (cur_bfd)->external_aux
+ + fh->iauxBase + sh.index + 1),
+ tpp, type_code, pname,
+ fh->fBigendian, sym_name);
+ break;
+
+ default:
+ complain (&illegal_forward_bt_complaint, tir.bt, sym_name);
+ *tpp = init_type (type_code, 0, 0, (char *) NULL,
+ current_objfile);
+ break;
+ }
+ return result;
+ }
+ else if (sh.st == stTypedef)
+ {
+ /* Parse the type for a normal typedef. This might recursively call
+ cross_ref till we get a non typedef'ed type.
+ FIXME: This is not correct behaviour, but gdb currently
+ cannot handle typedefs without type copying. But type copying is
+ impossible as we might have mutual forward references between
+ two files and the copied type would not get filled in when
+ we later parse its definition. */
+ *tpp = parse_type (xref_fd,
+ ecoff_data (cur_bfd)->external_aux + fh->iauxBase,
+ sh.index,
+ (int *)NULL,
+ fh->fBigendian,
+ (ecoff_data (cur_bfd)->ss
+ + fh->issBase + sh.iss));
+ }
+ else
+ {
+ /* Cross reference to a struct/union/enum which is defined
+ in another file in the same compilation unit but that file
+ has not been parsed yet.
+ Initialize the type only, it will be filled in when
+ it's definition is parsed. */
+ *tpp = init_type (type_code, 0, 0, (char *) NULL, current_objfile);
+ }
+ add_pending (fh, esh, *tpp);
+ }
+
+ /* We used one auxent normally, two if we got a "next one" rf. */
+ return result;
+}
+
+
+/* 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) == 0)
+ return sym;
+ bot++;
+ }
+ block = BLOCK_SUPERBLOCK (block);
+ if (block)
+ return mylookup_symbol (name, block, namespace, class);
+ return 0;
+}
+
+
+/* Add a new symbol S to a block B.
+ Infrequently, we will need to reallocate the block to make it bigger.
+ We only detect this case when adding to top_stack->cur_block, since
+ that's the only time we know how big the block is. FIXME. */
+
+static void
+add_symbol (s, b)
+ struct symbol *s;
+ struct block *b;
+{
+ int nsyms = BLOCK_NSYMS (b)++;
+ struct block *origb;
+ struct parse_stack *stackp;
+
+ if (b == top_stack->cur_block &&
+ nsyms >= top_stack->maxsyms)
+ {
+ complain (&block_overflow_complaint, SYMBOL_NAME (s));
+ /* In this case shrink_block is actually grow_block, since
+ BLOCK_NSYMS(b) is larger than its current size. */
+ origb = b;
+ b = shrink_block (top_stack->cur_block, top_stack->cur_st);
+
+ /* Now run through the stack replacing pointers to the
+ original block. shrink_block has already done this
+ for the blockvector and BLOCK_FUNCTION. */
+ for (stackp = top_stack; stackp; stackp = stackp->next)
+ {
+ if (stackp->cur_block == origb)
+ {
+ stackp->cur_block = b;
+ stackp->maxsyms = BLOCK_NSYMS (b);
+ }
+ }
+ }
+ BLOCK_SYM (b, nsyms) = s;
+}
+
+/* Add a new block B to a symtab S */
+
+static void
+add_block (b, s)
+ struct block *b;
+ struct symtab *s;
+{
+ struct blockvector *bv = BLOCKVECTOR (s);
+
+ bv = (struct blockvector *) xrealloc ((PTR) 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.
+
+ Combining lines with the same line number seems like a bad idea.
+ E.g: There could be a line number entry with the same line number after the
+ prologue and GDB should not ignore it (this is a better way to find
+ a prologue than mips_skip_prologue).
+ But due to the compressed line table format there are line number entries
+ for the same line which are needed to bridge the gap to the next
+ line number entry. These entries have a bogus address info with them
+ and we are unable to tell them from intended duplicate line number
+ entries.
+ This is another reason why -ggdb debugging format is preferable. */
+
+static int
+add_line (lt, lineno, adr, last)
+ struct linetable *lt;
+ int lineno;
+ CORE_ADDR adr;
+ int last;
+{
+ 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;
+}
+
+/* Sorting and reordering procedures */
+
+/* Blocks with a smaller low bound should come first */
+
+static int
+compare_blocks (arg1, arg2)
+ const PTR arg1;
+ const PTR arg2;
+{
+ register int addr_diff;
+ struct block **b1 = (struct block **) arg1;
+ struct block **b2 = (struct block **) arg2;
+
+ addr_diff = (BLOCK_START ((*b1))) - (BLOCK_START ((*b2)));
+ if (addr_diff == 0)
+ return (BLOCK_END ((*b2))) - (BLOCK_END ((*b1)));
+ return addr_diff;
+}
+
+/* Sort the blocks of a symtab S.
+ Reorder the blocks in the blockvector by code-address,
+ as required by some MI search routines */
+
+static void
+sort_blocks (s)
+ struct symtab *s;
+{
+ struct blockvector *bv = BLOCKVECTOR (s);
+
+ if (BLOCKVECTOR_NBLOCKS (bv) <= 2)
+ {
+ /* Cosmetic */
+ if (BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) == 0)
+ BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = 0;
+ if (BLOCK_END (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) == 0)
+ BLOCK_START (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) = 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, FIRST_LOCAL_BLOCK),
+ BLOCKVECTOR_NBLOCKS (bv) - FIRST_LOCAL_BLOCK,
+ sizeof (struct block *),
+ compare_blocks);
+
+ {
+ register CORE_ADDR high = 0;
+ register int i, j = BLOCKVECTOR_NBLOCKS (bv);
+
+ for (i = FIRST_LOCAL_BLOCK; i < j; i++)
+ if (high < BLOCK_END (BLOCKVECTOR_BLOCK (bv, i)))
+ high = BLOCK_END (BLOCKVECTOR_BLOCK (bv, i));
+ BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) = high;
+ }
+
+ BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)) =
+ BLOCK_START (BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK));
+
+ BLOCK_START (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) =
+ BLOCK_START (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
+ BLOCK_END (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) =
+ BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
+}
+
+
+/* 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, objfile)
+ char *name;
+ int maxsyms;
+ int maxlines;
+ struct objfile *objfile;
+{
+ struct symtab *s = allocate_symtab (name, objfile);
+
+ LINETABLE (s) = new_linetable (maxlines);
+
+ /* All symtabs must have at least two blocks */
+ BLOCKVECTOR (s) = new_bvect (2);
+ BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK) = new_block (maxsyms);
+ BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK) = new_block (maxsyms);
+ BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)) =
+ BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+
+ s->free_code = free_linetable;
+
+ return (s);
+}
+
+/* Allocate a new partial_symtab NAME */
+
+static struct partial_symtab *
+new_psymtab (name, objfile)
+ char *name;
+ struct objfile *objfile;
+{
+ struct partial_symtab *psymtab;
+
+ psymtab = allocate_psymtab (name, objfile);
+
+ /* Keep a backpointer to the file's symbols */
+
+ psymtab->read_symtab_private = ((char *)
+ obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct symloc)));
+ memset ((PTR) psymtab->read_symtab_private, 0, sizeof (struct symloc));
+ CUR_BFD (psymtab) = cur_bfd;
+
+ /* The way to turn this into a symtab is to call... */
+ psymtab->read_symtab = mipscoff_psymtab_to_symtab;
+ return (psymtab);
+}
+
+
+/* Allocate a linetable array of the given SIZE. Since the struct
+ already includes one item, we subtract one when calculating the
+ proper size to allocate. */
+
+static struct linetable *
+new_linetable (size)
+ int size;
+{
+ struct linetable *l;
+
+ size = (size - 1) * 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.
+
+ Since the struct linetable already includes one item, we subtract one when
+ calculating the proper size to allocate. */
+
+static struct linetable *
+shrink_linetable (lt)
+ struct linetable *lt;
+{
+
+ return (struct linetable *) xrealloc ((PTR) lt,
+ (sizeof (struct linetable)
+ + ((lt->nitems - 1)
+ * sizeof (lt->item))));
+}
+
+/* Allocate and zero a new blockvector of NBLOCKS blocks. */
+
+static struct blockvector *
+new_bvect (nblocks)
+ int 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 maxsyms;
+{
+ int size = sizeof (struct block) + (maxsyms - 1) * sizeof (struct symbol *);
+
+ return (struct block *) xzalloc (size);
+}
+
+/* Ooops, too big. Shrink block B in symtab S to its minimal size.
+ Shrink_block can also be used by add_symbol to grow a block. */
+
+static struct block *
+shrink_block (b, s)
+ struct block *b;
+ struct symtab *s;
+{
+ struct block *new;
+ struct blockvector *bv = BLOCKVECTOR (s);
+ int i;
+
+ /* Just reallocate it and fix references to the old one */
+
+ new = (struct block *) xrealloc ((PTR) b,
+ (sizeof (struct block)
+ + ((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 (new) && SYMBOL_BLOCK_VALUE (BLOCK_FUNCTION (new)) == b)
+ SYMBOL_BLOCK_VALUE (BLOCK_FUNCTION (new)) = 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;
+ return new;
+}
+
+/* Create a new symbol with printname NAME */
+
+static struct symbol *
+new_symbol (name)
+ char *name;
+{
+ struct symbol *s = ((struct symbol *)
+ obstack_alloc (&current_objfile->symbol_obstack,
+ sizeof (struct symbol)));
+
+ memset ((PTR) s, 0, sizeof (*s));
+ SYMBOL_NAME (s) = name;
+ SYMBOL_LANGUAGE (s) = psymtab_language;
+ SYMBOL_INIT_DEMANGLED_NAME (s, &current_objfile->symbol_obstack);
+ return s;
+}
+
+/* Create a new type with printname NAME */
+
+static struct type *
+new_type (name)
+ char *name;
+{
+ struct type *t;
+
+ t = alloc_type (current_objfile);
+ TYPE_NAME (t) = name;
+ TYPE_CPLUS_SPECIFIC (t) = (struct cplus_struct_type *) &cplus_struct_default;
+ return t;
+}
+
+
+/* Things used for calling functions in the inferior.
+ These functions are exported to our companion
+ mips-tdep.c file and are here because they play
+ with the symbol-table explicitly. */
+
+/* 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 void
+fixup_sigtramp ()
+{
+ struct symbol *s;
+ struct symtab *st;
+ struct block *b, *b0 = NULL;
+
+ sigtramp_address = -1;
+
+ /* We have to handle the following cases here:
+ a) The Mips library has a sigtramp label within sigvec.
+ b) Irix has a _sigtramp which we want to use, but it also has sigvec. */
+ s = lookup_symbol ("sigvec", 0, VAR_NAMESPACE, 0, NULL);
+ if (s != 0)
+ {
+ b0 = SYMBOL_BLOCK_VALUE (s);
+ s = lookup_symbol ("sigtramp", b0, VAR_NAMESPACE, 0, NULL);
+ }
+ if (s == 0)
+ {
+ /* No sigvec or no sigtramp inside sigvec, try _sigtramp. */
+ s = lookup_symbol ("_sigtramp", 0, VAR_NAMESPACE, 0, NULL);
+ }
+
+ /* But maybe this program uses its own version of sigvec */
+ if (s == 0)
+ return;
+
+ /* Did we or MIPSco fix the library ? */
+ if (SYMBOL_CLASS (s) == LOC_BLOCK)
+ {
+ sigtramp_address = BLOCK_START (SYMBOL_BLOCK_VALUE (s));
+ sigtramp_end = BLOCK_END (SYMBOL_BLOCK_VALUE (s));
+ return;
+ }
+
+ sigtramp_address = SYMBOL_VALUE (s);
+ sigtramp_end = sigtramp_address + 0x88; /* black magic */
+
+ /* 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) = init_type (TYPE_CODE_FUNC, 4, 0, (char *) NULL,
+ st->objfile);
+ TYPE_TARGET_TYPE (SYMBOL_TYPE (s)) = builtin_type_void;
+
+ /* Need a block to allocate MIPS_EFI_SYMBOL_NAME 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 MIPS_EFI_SYMBOL_NAME entry 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->pdr.frameoffset = 0x150;
+ e->pdr.framereg = SP_REGNUM;
+ /* read_next_frame_reg provides the true pc at the time of signal */
+ e->pdr.pcreg = PC_REGNUM;
+ e->pdr.regmask = -2;
+ e->pdr.regoffset = -(41 * sizeof (int));
+ e->pdr.fregmask = -1;
+ e->pdr.fregoffset = -(7 * sizeof (int));
+ e->pdr.isym = (long) s;
+ e->pdr.adr = sigtramp_address;
+
+ current_objfile = st->objfile; /* Keep new_symbol happy */
+ s = new_symbol (MIPS_EFI_SYMBOL_NAME);
+ SYMBOL_VALUE (s) = (long) e;
+ SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_CONST;
+ SYMBOL_TYPE (s) = builtin_type_void;
+ current_objfile = NULL;
+ }
+
+ BLOCK_SYM (b, BLOCK_NSYMS (b)++) = s;
+}
+
+
+/* Fake up identical offsets for all sections. */
+
+struct section_offsets *
+mipscoff_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ section_offsets = ((struct section_offsets *)
+ obstack_alloc (&objfile->psymbol_obstack,
+ (sizeof (struct section_offsets)
+ + (sizeof (section_offsets->offsets)
+ * (SECT_OFF_MAX - 1)))));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+/* Initialization */
+
+static struct sym_fns ecoff_sym_fns =
+{
+ "ecoff", /* sym_name: name or name prefix of BFD target type */
+ 5, /* sym_namelen: number of significant sym_name chars */
+ mipscoff_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ mipscoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ mipscoff_symfile_read, /* sym_read: read a symbol file into symtab */
+ mipscoff_symfile_finish, /* sym_finish: finished with file, cleanup */
+ mipscoff_symfile_offsets, /* sym_offsets: dummy FIXME til implem sym reloc */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+
+void
+_initialize_mipsread ()
+{
+ add_symtab_fns (&ecoff_sym_fns);
+
+ /* Missing basic types */
+
+ builtin_type_string =
+ init_type (TYPE_CODE_STRING,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "string",
+ (struct objfile *) NULL);
+ builtin_type_complex =
+ init_type (TYPE_CODE_FLT,
+ TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0, "complex",
+ (struct objfile *) NULL);
+ builtin_type_double_complex =
+ init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0, "double complex",
+ (struct objfile *) NULL);
+ builtin_type_fixed_dec =
+ init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "fixed decimal",
+ (struct objfile *) NULL);
+ builtin_type_float_dec =
+ init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "floating decimal",
+ (struct objfile *) NULL);
+}
diff --git a/gnu/usr.bin/gdb/gdb/nlmread.c b/gnu/usr.bin/gdb/gdb/nlmread.c
new file mode 100644
index 000000000000..fde3af249328
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/nlmread.c
@@ -0,0 +1,300 @@
+/* Read NLM (NetWare Loadable Module) format executable files for GDB.
+ Copyright 1993 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+
+static void
+nlm_new_init PARAMS ((struct objfile *));
+
+static void
+nlm_symfile_init PARAMS ((struct objfile *));
+
+static void
+nlm_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+nlm_symfile_finish PARAMS ((struct objfile *));
+
+static void
+nlm_symtab_read PARAMS ((bfd *, CORE_ADDR, struct objfile *));
+
+static struct section_offsets *
+nlm_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
+ struct objfile *));
+
+
+/* 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).
+
+ We reinitialize buildsym, since gdb will be able to read stabs from an NLM
+ file at some point in the near future. */
+
+static void
+nlm_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+
+/* NLM specific initialization routine for reading symbols.
+
+ It is passed a pointer to 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 can fill with goodies.
+
+ For now at least, we have nothing in particular to do, so this function is
+ just a stub. */
+
+static void
+nlm_symfile_init (ignore)
+ struct objfile *ignore;
+{
+}
+
+static void
+record_minimal_symbol (name, address, ms_type, objfile)
+ char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ struct objfile *objfile;
+{
+ name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
+ prim_record_minimal_symbol (name, address, ms_type);
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ nlm_symtab_read -- read the symbol table of an NLM file
+
+SYNOPSIS
+
+ void nlm_symtab_read (bfd *abfd, CORE_ADDR addr,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given an open bfd, a base address to relocate symbols to, and a
+ flag that specifies whether or not this bfd is for an executable
+ or not (may be shared library for example), add all the global
+ function and data symbols to the minimal symbol table.
+*/
+
+static void
+nlm_symtab_read (abfd, addr, objfile)
+ bfd *abfd;
+ CORE_ADDR addr;
+ struct objfile *objfile;
+{
+ unsigned int storage_needed;
+ asymbol *sym;
+ asymbol **symbol_table;
+ unsigned int number_of_symbols;
+ unsigned int i;
+ struct cleanup *back_to;
+ CORE_ADDR symaddr;
+ enum minimal_symbol_type ms_type;
+
+ storage_needed = get_symtab_upper_bound (abfd);
+ if (storage_needed > 0)
+ {
+ symbol_table = (asymbol **) xmalloc (storage_needed);
+ back_to = make_cleanup (free, symbol_table);
+ number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ sym = symbol_table[i];
+ if (sym -> flags & BSF_GLOBAL)
+ {
+ /* Bfd symbols are section relative. */
+ symaddr = sym -> value + sym -> section -> vma;
+ /* Relocate all non-absolute symbols by base address. */
+ if (sym -> section != &bfd_abs_section)
+ {
+ symaddr += addr;
+ }
+
+ /* For non-absolute symbols, use the type of the section
+ they are relative to, to intuit text/data. Bfd provides
+ no way of figuring this out for absolute symbols. */
+ if (sym -> section -> flags & SEC_CODE)
+ {
+ ms_type = mst_text;
+ }
+ else if (sym -> section -> flags & SEC_DATA)
+ {
+ ms_type = mst_data;
+ }
+ else
+ {
+ ms_type = mst_unknown;
+ }
+ record_minimal_symbol ((char *) sym -> name, symaddr, ms_type,
+ objfile);
+ }
+ }
+ do_cleanups (back_to);
+ }
+}
+
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to nlm_symfile_init, which
+ currently does nothing.
+
+ SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
+ in each section. We simplify it down to a single offset for all
+ symbols. FIXME.
+
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file).
+
+ This function only does the minimum work necessary for letting the
+ user "name" things symbolically; it does not read the entire symtab.
+ Instead, it reads the external and static symbols and puts 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 symbols
+ for real.
+
+ Note that NLM files have two sets of information that is potentially
+ useful for building gdb's minimal symbol table. The first is a list
+ of the publically exported symbols, and is currently used to build
+ bfd's canonical symbol table. The second is an optional native debugging
+ format which contains additional symbols (and possibly duplicates of
+ the publically exported symbols). The optional native debugging format
+ is not currently used. */
+
+static void
+nlm_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ bfd *abfd = objfile -> obfd;
+ struct cleanup *back_to;
+ CORE_ADDR offset;
+
+ init_minimal_symbol_collection ();
+ back_to = make_cleanup (discard_minimal_symbols, 0);
+
+ /* FIXME, should take a section_offsets param, not just an offset. */
+
+ offset = ANOFFSET (section_offsets, 0);
+
+ /* Process the NLM export records, which become the bfd's canonical symbol
+ table. */
+
+ nlm_symtab_read (abfd, offset, objfile);
+
+ /* FIXME: We could locate and read the optional native debugging format
+ here and add the symbols to the minimal symbol table. */
+
+ if (!have_partial_symbols ())
+ {
+ wrap_here ("");
+ printf_filtered ("(no debugging symbols found)...");
+ wrap_here ("");
+ }
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ do_cleanups (back_to);
+}
+
+
+/* Perform any local cleanups required when we are done with a particular
+ objfile. I.E, we are in the process of discarding all symbol information
+ for an objfile, freeing up all memory held for it, and unlinking the
+ objfile struct from the global list of known objfiles. */
+
+static void
+nlm_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_private != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_private);
+ }
+}
+
+/* NLM specific parsing routine for section offsets.
+ FIXME: This may or may not be necessary. All the symbol readers seem
+ to have similar code. See if it can be generalized and moved elsewhere. */
+
+static
+struct section_offsets *
+nlm_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+{
+ struct section_offsets *section_offsets;
+ int i;
+
+ section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets) +
+ sizeof (section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ {
+ ANOFFSET (section_offsets, i) = addr;
+ }
+
+ return (section_offsets);
+}
+
+
+/* Register that we are able to handle NLM file format. */
+
+static struct sym_fns nlm_sym_fns =
+{
+ "nlm", /* sym_name: name or name prefix of BFD target type */
+ 3, /* sym_namelen: number of significant sym_name chars */
+ nlm_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ nlm_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ nlm_symfile_read, /* sym_read: read a symbol file into symtab */
+ nlm_symfile_finish, /* sym_finish: finished with file, cleanup */
+ nlm_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_nlmread ()
+{
+ add_symtab_fns (&nlm_sym_fns);
+}
diff --git a/gnu/usr.bin/gdb/gdb/nm.h b/gnu/usr.bin/gdb/gdb/nm.h
new file mode 100644
index 000000000000..a7af00f33d87
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/nm.h
@@ -0,0 +1,44 @@
+/* Native-dependent definitions for Intel 386 running BSD Unix, for GDB.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef NM_FREEBSD_H
+#define NM_FREEBSD_H
+
+/* Be shared lib aware */
+#include "solib.h"
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#include <machine/vmparam.h>
+#define KERNEL_U_ADDR USRSTACK
+
+/* #undef FLOAT_INFO /* No float info yet */
+#define FLOAT_INFO extern i386_float_info (); \
+ i386_float_info ()
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+#define PTRACE_ARG3_TYPE char*
+
+#endif /* NM_FREEBSD_H */
diff --git a/gnu/usr.bin/gdb/gdb/objfiles.c b/gnu/usr.bin/gdb/gdb/objfiles.c
new file mode 100644
index 000000000000..b111f005c05d
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/objfiles.c
@@ -0,0 +1,773 @@
+/* GDB routines for manipulating objfiles.
+ Copyright 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file contains support routines for creating, manipulating, and
+ destroying objfile structures. */
+
+#include "defs.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "target.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <obstack.h>
+
+/* Prototypes for local functions */
+
+#if !defined(NO_MMALLOC) && defined(HAVE_MMAP)
+
+static int
+open_existing_mapped_file PARAMS ((char *, long, int));
+
+static int
+open_mapped_file PARAMS ((char *filename, long mtime, int mapped));
+
+static CORE_ADDR
+map_to_address PARAMS ((void));
+
+#endif /* !defined(NO_MMALLOC) && defined(HAVE_MMAP) */
+
+/* Message to be printed before the error message, when an error occurs. */
+
+extern char *error_pre_print;
+
+/* Externally visible variables that are owned by this module.
+ See declarations in objfile.h for more info. */
+
+struct objfile *object_files; /* Linked list of all objfiles */
+struct objfile *current_objfile; /* For symbol file being read in */
+struct objfile *symfile_objfile; /* Main symbol table loaded from */
+
+int mapped_symbol_files; /* Try to use mapped symbol files */
+
+/* Locate all mappable sections of a BFD file.
+ objfile_p_char is a char * to get it through
+ bfd_map_over_sections; we cast it back to its proper type. */
+
+static void
+add_to_objfile_sections (abfd, asect, objfile_p_char)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR objfile_p_char;
+{
+ struct objfile *objfile = (struct objfile *) objfile_p_char;
+ struct obj_section section;
+ 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;
+ if (0 == bfd_section_size (abfd, asect))
+ return;
+ section.offset = 0;
+ section.objfile = objfile;
+ section.sec_ptr = asect;
+ section.addr = bfd_section_vma (abfd, asect);
+ section.endaddr = section.addr + bfd_section_size (abfd, asect);
+ obstack_grow (&objfile->psymbol_obstack, &section, sizeof(section));
+ objfile->sections_end = (struct obj_section *) (((unsigned long) objfile->sections_end) + 1);
+}
+
+/* Builds a section table for OBJFILE.
+ Returns 0 if OK, 1 on error. */
+
+static int
+build_objfile_section_table (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sections)
+ abort();
+
+ objfile->sections_end = 0;
+ bfd_map_over_sections (objfile->obfd, add_to_objfile_sections, (char *)objfile);
+ objfile->sections = (struct obj_section *)
+ obstack_finish (&objfile->psymbol_obstack);
+ objfile->sections_end = objfile->sections + (unsigned long) objfile->sections_end;
+ return(0);
+}
+
+/* Given a pointer to an initialized bfd (ABFD) and a flag that indicates
+ whether or not an objfile is to be mapped (MAPPED), allocate a new objfile
+ struct, fill it in as best we can, link it into the list of all known
+ objfiles, and return a pointer to the new objfile struct. */
+
+struct objfile *
+allocate_objfile (abfd, mapped)
+ bfd *abfd;
+ int mapped;
+{
+ struct objfile *objfile = NULL;
+ int fd;
+ PTR md;
+ CORE_ADDR mapto;
+
+ mapped |= mapped_symbol_files;
+
+#if !defined(NO_MMALLOC) && defined(HAVE_MMAP)
+
+ /* If we can support mapped symbol files, try to open/reopen the mapped file
+ that corresponds to the file from which we wish to read symbols. If the
+ objfile is to be mapped, we must malloc the structure itself using the
+ mmap version, and arrange that all memory allocation for the objfile uses
+ the mmap routines. If we are reusing an existing mapped file, from which
+ we get our objfile pointer, we have to make sure that we update the
+ pointers to the alloc/free functions in the obstack, in case these
+ functions have moved within the current gdb. */
+
+ fd = open_mapped_file (bfd_get_filename (abfd), bfd_get_mtime (abfd),
+ mapped);
+ if (fd >= 0)
+ {
+ if (((mapto = map_to_address ()) == 0) ||
+ ((md = mmalloc_attach (fd, (PTR) mapto)) == NULL))
+ {
+ close (fd);
+ }
+ else if ((objfile = (struct objfile *) mmalloc_getkey (md, 0)) != NULL)
+ {
+ /* Update memory corruption handler function addresses. */
+ init_malloc (md);
+ objfile -> md = md;
+ objfile -> mmfd = fd;
+ /* Update pointers to functions to *our* copies */
+ obstack_chunkfun (&objfile -> psymbol_obstack, xmmalloc);
+ obstack_freefun (&objfile -> psymbol_obstack, mfree);
+ obstack_chunkfun (&objfile -> symbol_obstack, xmmalloc);
+ obstack_freefun (&objfile -> symbol_obstack, mfree);
+ obstack_chunkfun (&objfile -> type_obstack, xmmalloc);
+ obstack_freefun (&objfile -> type_obstack, mfree);
+ /* If already in objfile list, unlink it. */
+ unlink_objfile (objfile);
+ /* Forget things specific to a particular gdb, may have changed. */
+ objfile -> sf = NULL;
+ }
+ else
+ {
+ /* Set up to detect internal memory corruption. MUST be done before
+ the first malloc. See comments in init_malloc() and mmcheck(). */
+ init_malloc (md);
+ objfile = (struct objfile *) xmmalloc (md, sizeof (struct objfile));
+ memset (objfile, 0, sizeof (struct objfile));
+ objfile -> md = md;
+ objfile -> mmfd = fd;
+ objfile -> flags |= OBJF_MAPPED;
+ mmalloc_setkey (objfile -> md, 0, objfile);
+ obstack_specify_allocation_with_arg (&objfile -> psymbol_obstack,
+ 0, 0, xmmalloc, mfree,
+ objfile -> md);
+ obstack_specify_allocation_with_arg (&objfile -> symbol_obstack,
+ 0, 0, xmmalloc, mfree,
+ objfile -> md);
+ obstack_specify_allocation_with_arg (&objfile -> type_obstack,
+ 0, 0, xmmalloc, mfree,
+ objfile -> md);
+ }
+ }
+
+ if (mapped && (objfile == NULL))
+ {
+ warning ("symbol table for '%s' will not be mapped",
+ bfd_get_filename (abfd));
+ }
+
+#else /* defined(NO_MMALLOC) || !defined(HAVE_MMAP) */
+
+ if (mapped)
+ {
+ warning ("this version of gdb does not support mapped symbol tables.");
+
+ /* Turn off the global flag so we don't try to do mapped symbol tables
+ any more, which shuts up gdb unless the user specifically gives the
+ "mapped" keyword again. */
+
+ mapped_symbol_files = 0;
+ }
+
+#endif /* !defined(NO_MMALLOC) && defined(HAVE_MMAP) */
+
+ /* If we don't support mapped symbol files, didn't ask for the file to be
+ mapped, or failed to open the mapped file for some reason, then revert
+ back to an unmapped objfile. */
+
+ if (objfile == NULL)
+ {
+ objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
+ memset (objfile, 0, sizeof (struct objfile));
+ objfile -> md = NULL;
+ obstack_specify_allocation (&objfile -> psymbol_obstack, 0, 0, xmalloc,
+ free);
+ obstack_specify_allocation (&objfile -> symbol_obstack, 0, 0, xmalloc,
+ free);
+ obstack_specify_allocation (&objfile -> type_obstack, 0, 0, xmalloc,
+ free);
+ }
+
+ /* Update the per-objfile information that comes from the bfd, ensuring
+ that any data that is reference is saved in the per-objfile data
+ region. */
+
+ objfile -> obfd = abfd;
+ if (objfile -> name != NULL)
+ {
+ mfree (objfile -> md, objfile -> name);
+ }
+ objfile -> name = mstrsave (objfile -> md, bfd_get_filename (abfd));
+ objfile -> mtime = bfd_get_mtime (abfd);
+
+ /* Build section table. */
+
+ if (build_objfile_section_table (objfile))
+ {
+ error ("Can't find the file sections in `%s': %s",
+ objfile -> name, bfd_errmsg (bfd_error));
+ }
+
+ /* Push this file onto the head of the linked list of other such files. */
+
+ objfile -> next = object_files;
+ object_files = objfile;
+
+ return (objfile);
+}
+
+/* Unlink OBJFILE from the list of known objfiles, if it is found in the
+ list.
+
+ It is not a bug, or error, to call this function if OBJFILE is not known
+ to be in the current list. This is done in the case of mapped objfiles,
+ for example, just to ensure that the mapped objfile doesn't appear twice
+ in the list. Since the list is threaded, linking in a mapped objfile
+ twice would create a circular list.
+
+ If OBJFILE turns out to be in the list, we zap it's NEXT pointer after
+ unlinking it, just to ensure that we have completely severed any linkages
+ between the OBJFILE and the list. */
+
+void
+unlink_objfile (objfile)
+ struct objfile *objfile;
+{
+ struct objfile** objpp;
+
+ for (objpp = &object_files; *objpp != NULL; objpp = &((*objpp) -> next))
+ {
+ if (*objpp == objfile)
+ {
+ *objpp = (*objpp) -> next;
+ objfile -> next = NULL;
+ break;
+ }
+ }
+}
+
+
+/* Destroy an objfile and all the symtabs and psymtabs under it. Note
+ that as much as possible is allocated on the symbol_obstack and
+ psymbol_obstack, so that the memory can be efficiently freed.
+
+ Things which we do NOT free because they are not in malloc'd memory
+ or not in memory specific to the objfile include:
+
+ objfile -> sf
+
+ FIXME: If the objfile is using reusable symbol information (via mmalloc),
+ then we need to take into account the fact that more than one process
+ may be using the symbol information at the same time (when mmalloc is
+ extended to support cooperative locking). When more than one process
+ is using the mapped symbol info, we need to be more careful about when
+ we free objects in the reusable area. */
+
+void
+free_objfile (objfile)
+ struct objfile *objfile;
+{
+ int mmfd;
+
+ /* First do any symbol file specific actions required when we are
+ finished with a particular symbol file. Note that if the objfile
+ is using reusable symbol information (via mmalloc) then each of
+ these routines is responsible for doing the correct thing, either
+ freeing things which are valid only during this particular gdb
+ execution, or leaving them to be reused during the next one. */
+
+ if (objfile -> sf != NULL)
+ {
+ (*objfile -> sf -> sym_finish) (objfile);
+ }
+
+ /* We always close the bfd. */
+
+ if (objfile -> obfd != NULL)
+ {
+ char *name = bfd_get_filename (objfile->obfd);
+ bfd_close (objfile -> obfd);
+ free (name);
+ }
+
+ /* Remove it from the chain of all objfiles. */
+
+ unlink_objfile (objfile);
+
+ /* Before the symbol table code was redone to make it easier to
+ selectively load and remove information particular to a specific
+ linkage unit, gdb used to do these things whenever the monolithic
+ symbol table was blown away. How much still needs to be done
+ is unknown, but we play it safe for now and keep each action until
+ it is shown to be no longer needed. */
+
+#if defined (CLEAR_SOLIB)
+ CLEAR_SOLIB ();
+ /* CLEAR_SOLIB closes the bfd's for any shared libraries. But
+ the to_sections for a core file might refer to those bfd's. So
+ detach any core file. */
+ {
+ struct target_ops *t = find_core_target ();
+ if (t != NULL)
+ (t->to_detach) (NULL, 0);
+ }
+#endif
+ clear_pc_function_cache ();
+
+ /* The last thing we do is free the objfile struct itself for the
+ non-reusable case, or detach from the mapped file for the reusable
+ case. Note that the mmalloc_detach or the mfree is the last thing
+ we can do with this objfile. */
+
+#if !defined(NO_MMALLOC) && defined(HAVE_MMAP)
+
+ if (objfile -> flags & OBJF_MAPPED)
+ {
+ /* Remember the fd so we can close it. We can't close it before
+ doing the detach, and after the detach the objfile is gone. */
+ mmfd = objfile -> mmfd;
+ mmalloc_detach (objfile -> md);
+ objfile = NULL;
+ close (mmfd);
+ }
+
+#endif /* !defined(NO_MMALLOC) && defined(HAVE_MMAP) */
+
+ /* If we still have an objfile, then either we don't support reusable
+ objfiles or this one was not reusable. So free it normally. */
+
+ if (objfile != NULL)
+ {
+ if (objfile -> name != NULL)
+ {
+ mfree (objfile -> md, objfile -> name);
+ }
+ if (objfile->global_psymbols.list)
+ mfree (objfile->md, objfile->global_psymbols.list);
+ if (objfile->static_psymbols.list)
+ mfree (objfile->md, objfile->static_psymbols.list);
+ /* Free the obstacks for non-reusable objfiles */
+ obstack_free (&objfile -> psymbol_obstack, 0);
+ obstack_free (&objfile -> symbol_obstack, 0);
+ obstack_free (&objfile -> type_obstack, 0);
+ mfree (objfile -> md, objfile);
+ objfile = NULL;
+ }
+}
+
+
+/* Free all the object files at once and clean up their users. */
+
+void
+free_all_objfiles ()
+{
+ struct objfile *objfile, *temp;
+
+ ALL_OBJFILES_SAFE (objfile, temp)
+ {
+ free_objfile (objfile);
+ }
+ clear_symtab_users ();
+}
+
+/* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS
+ entries in new_offsets. */
+void
+objfile_relocate (objfile, new_offsets)
+ struct objfile *objfile;
+ struct section_offsets *new_offsets;
+{
+ struct section_offsets *delta = (struct section_offsets *) alloca
+ (sizeof (struct section_offsets)
+ + objfile->num_sections * sizeof (delta->offsets));
+
+ {
+ int i;
+ int something_changed = 0;
+ for (i = 0; i < objfile->num_sections; ++i)
+ {
+ ANOFFSET (delta, i) =
+ ANOFFSET (new_offsets, i) - ANOFFSET (objfile->section_offsets, i);
+ if (ANOFFSET (delta, i) != 0)
+ something_changed = 1;
+ }
+ if (!something_changed)
+ return;
+ }
+
+ /* OK, get all the symtabs. */
+ {
+ struct symtab *s;
+
+ for (s = objfile->symtabs; s; s = s->next)
+ {
+ struct linetable *l;
+ struct blockvector *bv;
+ int i;
+
+ /* First the line table. */
+ l = LINETABLE (s);
+ if (l)
+ {
+ for (i = 0; i < l->nitems; ++i)
+ l->item[i].pc += ANOFFSET (delta, s->block_line_section);
+ }
+
+ /* Don't relocate a shared blockvector more than once. */
+ if (!s->primary)
+ continue;
+
+ bv = BLOCKVECTOR (s);
+ for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); ++i)
+ {
+ struct block *b;
+ int j;
+
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ BLOCK_START (b) += ANOFFSET (delta, s->block_line_section);
+ BLOCK_END (b) += ANOFFSET (delta, s->block_line_section);
+
+ for (j = 0; j < BLOCK_NSYMS (b); ++j)
+ {
+ struct symbol *sym = BLOCK_SYM (b, j);
+ /* The RS6000 code from which this was taken skipped
+ any symbols in STRUCT_NAMESPACE or UNDEF_NAMESPACE.
+ But I'm leaving out that test, on the theory that
+ they can't possibly pass the tests below. */
+ if ((SYMBOL_CLASS (sym) == LOC_LABEL
+ || SYMBOL_CLASS (sym) == LOC_STATIC)
+ && SYMBOL_SECTION (sym) >= 0)
+ {
+ SYMBOL_VALUE_ADDRESS (sym) +=
+ ANOFFSET (delta, SYMBOL_SECTION (sym));
+ }
+ }
+ }
+ }
+ }
+
+ {
+ struct partial_symtab *p;
+
+ ALL_OBJFILE_PSYMTABS (objfile, p)
+ {
+ /* FIXME: specific to symbol readers which use gdb-stabs.h.
+ We can only get away with it since objfile_relocate is only
+ used on XCOFF, which lacks psymtabs, and for gdb-stabs.h
+ targets. */
+ p->textlow += ANOFFSET (delta, SECT_OFF_TEXT);
+ p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT);
+ }
+ }
+
+ {
+ struct partial_symbol *psym;
+
+ for (psym = objfile->global_psymbols.list;
+ psym < objfile->global_psymbols.next;
+ psym++)
+ if (SYMBOL_SECTION (psym) >= 0)
+ SYMBOL_VALUE_ADDRESS (psym) += ANOFFSET (delta, SYMBOL_SECTION (psym));
+ for (psym = objfile->static_psymbols.list;
+ psym < objfile->static_psymbols.next;
+ psym++)
+ if (SYMBOL_SECTION (psym) >= 0)
+ SYMBOL_VALUE_ADDRESS (psym) += ANOFFSET (delta, SYMBOL_SECTION (psym));
+ }
+
+ {
+ struct minimal_symbol *msym;
+ ALL_OBJFILE_MSYMBOLS (objfile, msym)
+ if (SYMBOL_SECTION (msym) >= 0)
+ SYMBOL_VALUE_ADDRESS (msym) += ANOFFSET (delta, SYMBOL_SECTION (msym));
+ }
+
+ {
+ int i;
+ for (i = 0; i < objfile->num_sections; ++i)
+ ANOFFSET (objfile->section_offsets, i) = ANOFFSET (new_offsets, i);
+ }
+}
+
+/* Many places in gdb want to test just to see if we have any partial
+ symbols available. This function returns zero if none are currently
+ available, nonzero otherwise. */
+
+int
+have_partial_symbols ()
+{
+ struct objfile *ofp;
+
+ ALL_OBJFILES (ofp)
+ {
+ if (ofp -> psymtabs != NULL)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Many places in gdb want to test just to see if we have any full
+ symbols available. This function returns zero if none are currently
+ available, nonzero otherwise. */
+
+int
+have_full_symbols ()
+{
+ struct objfile *ofp;
+
+ ALL_OBJFILES (ofp)
+ {
+ if (ofp -> symtabs != NULL)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Many places in gdb want to test just to see if we have any minimal
+ symbols available. This function returns zero if none are currently
+ available, nonzero otherwise. */
+
+int
+have_minimal_symbols ()
+{
+ struct objfile *ofp;
+
+ ALL_OBJFILES (ofp)
+ {
+ if (ofp -> msymbols != NULL)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#if !defined(NO_MMALLOC) && defined(HAVE_MMAP)
+
+/* Given the name of a mapped symbol file in SYMSFILENAME, and the timestamp
+ of the corresponding symbol file in MTIME, try to open an existing file
+ with the name SYMSFILENAME and verify it is more recent than the base
+ file by checking it's timestamp against MTIME.
+
+ If SYMSFILENAME does not exist (or can't be stat'd), simply returns -1.
+
+ If SYMSFILENAME does exist, but is out of date, we check to see if the
+ user has specified creation of a mapped file. If so, we don't issue
+ any warning message because we will be creating a new mapped file anyway,
+ overwriting the old one. If not, then we issue a warning message so that
+ the user will know why we aren't using this existing mapped symbol file.
+ In either case, we return -1.
+
+ If SYMSFILENAME does exist and is not out of date, but can't be opened for
+ some reason, then prints an appropriate system error message and returns -1.
+
+ Otherwise, returns the open file descriptor. */
+
+static int
+open_existing_mapped_file (symsfilename, mtime, mapped)
+ char *symsfilename;
+ long mtime;
+ int mapped;
+{
+ int fd = -1;
+ struct stat sbuf;
+
+ if (stat (symsfilename, &sbuf) == 0)
+ {
+ if (sbuf.st_mtime < mtime)
+ {
+ if (!mapped)
+ {
+ warning ("mapped symbol file `%s' is out of date, ignored it",
+ symsfilename);
+ }
+ }
+ else if ((fd = open (symsfilename, O_RDWR)) < 0)
+ {
+ if (error_pre_print)
+ {
+ printf (error_pre_print);
+ }
+ print_sys_errmsg (symsfilename, errno);
+ }
+ }
+ return (fd);
+}
+
+/* Look for a mapped symbol file that corresponds to FILENAME and is more
+ recent than MTIME. If MAPPED is nonzero, the user has asked that gdb
+ use a mapped symbol file for this file, so create a new one if one does
+ not currently exist.
+
+ If found, then return an open file descriptor for the file, otherwise
+ return -1.
+
+ This routine is responsible for implementing the policy that generates
+ the name of the mapped symbol file from the name of a file containing
+ symbols that gdb would like to read. Currently this policy is to append
+ ".syms" to the name of the file.
+
+ This routine is also responsible for implementing the policy that
+ determines where the mapped symbol file is found (the search path).
+ This policy is that when reading an existing mapped file, a file of
+ the correct name in the current directory takes precedence over a
+ file of the correct name in the same directory as the symbol file.
+ When creating a new mapped file, it is always created in the current
+ directory. This helps to minimize the chances of a user unknowingly
+ creating big mapped files in places like /bin and /usr/local/bin, and
+ allows a local copy to override a manually installed global copy (in
+ /bin for example). */
+
+static int
+open_mapped_file (filename, mtime, mapped)
+ char *filename;
+ long mtime;
+ int mapped;
+{
+ int fd;
+ char *symsfilename;
+
+ /* First try to open an existing file in the current directory, and
+ then try the directory where the symbol file is located. */
+
+ symsfilename = concat ("./", basename (filename), ".syms", (char *) NULL);
+ if ((fd = open_existing_mapped_file (symsfilename, mtime, mapped)) < 0)
+ {
+ free (symsfilename);
+ symsfilename = concat (filename, ".syms", (char *) NULL);
+ fd = open_existing_mapped_file (symsfilename, mtime, mapped);
+ }
+
+ /* If we don't have an open file by now, then either the file does not
+ already exist, or the base file has changed since it was created. In
+ either case, if the user has specified use of a mapped file, then
+ create a new mapped file, truncating any existing one. If we can't
+ create one, print a system error message saying why we can't.
+
+ By default the file is rw for everyone, with the user's umask taking
+ care of turning off the permissions the user wants off. */
+
+ if ((fd < 0) && mapped)
+ {
+ free (symsfilename);
+ symsfilename = concat ("./", basename (filename), ".syms",
+ (char *) NULL);
+ if ((fd = open (symsfilename, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
+ {
+ if (error_pre_print)
+ {
+ printf (error_pre_print);
+ }
+ print_sys_errmsg (symsfilename, errno);
+ }
+ }
+
+ free (symsfilename);
+ return (fd);
+}
+
+/* Return the base address at which we would like the next objfile's
+ mapped data to start.
+
+ For now, we use the kludge that the configuration specifies a base
+ address to which it is safe to map the first mmalloc heap, and an
+ increment to add to this address for each successive heap. There are
+ a lot of issues to deal with here to make this work reasonably, including:
+
+ Avoid memory collisions with existing mapped address spaces
+
+ Reclaim address spaces when their mmalloc heaps are unmapped
+
+ When mmalloc heaps are shared between processes they have to be
+ mapped at the same addresses in each
+
+ Once created, a mmalloc heap that is to be mapped back in must be
+ mapped at the original address. I.E. each objfile will expect to
+ be remapped at it's original address. This becomes a problem if
+ the desired address is already in use.
+
+ etc, etc, etc.
+
+ */
+
+
+static CORE_ADDR
+map_to_address ()
+{
+
+#if defined(MMAP_BASE_ADDRESS) && defined (MMAP_INCREMENT)
+
+ static CORE_ADDR next = MMAP_BASE_ADDRESS;
+ CORE_ADDR mapto = next;
+
+ next += MMAP_INCREMENT;
+ return (mapto);
+
+#else
+
+ return (0);
+
+#endif
+
+}
+
+#endif /* !defined(NO_MMALLOC) && defined(HAVE_MMAP) */
+
+/* Returns a section whose range includes PC or NULL if none found. */
+
+struct obj_section *
+find_pc_section(pc)
+ CORE_ADDR pc;
+{
+ struct obj_section *s;
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ for (s = objfile->sections; s < objfile->sections_end; ++s)
+ if (s->addr <= pc
+ && pc < s->endaddr)
+ return(s);
+
+ return(NULL);
+}
diff --git a/gnu/usr.bin/gdb/gdb/objfiles.h b/gnu/usr.bin/gdb/gdb/objfiles.h
new file mode 100644
index 000000000000..50226ff47e77
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/objfiles.h
@@ -0,0 +1,437 @@
+/* Definitions for symbol file management in GDB.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (OBJFILES_H)
+#define OBJFILES_H
+
+/* This structure maintains information on a per-objfile basis about the
+ "entry point" of the objfile, and the scope within which the entry point
+ exists. It is possible that gdb will see more than one objfile that is
+ executable, each with it's own entry point.
+
+ For example, for dynamically linked executables in SVR4, the dynamic linker
+ code is contained within the shared C library, which is actually executable
+ and is run by the kernel first when an exec is done of a user executable
+ that is dynamically linked. The dynamic linker within the shared C library
+ then maps in the various program segments in the user executable and jumps
+ to the user executable's recorded entry point, as if the call had been made
+ directly by the kernel.
+
+ The traditional gdb method of using this info is to use the recorded entry
+ point to set the variables entry_file_lowpc and entry_file_highpc from
+ the debugging information, where these values are the starting address
+ (inclusive) and ending address (exclusive) of the instruction space in the
+ executable which correspond to the "startup file", I.E. crt0.o in most
+ cases. 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 (or top, depending
+ upon your stack orientation).
+
+ Gdb also supports an alternate method to avoid running off the top/bottom
+ of the stack.
+
+ There are two frames that are "special", the frame for the function
+ containing the process entry point, since it has no predecessor frame,
+ and the frame for the function containing the user code entry point
+ (the main() function), since all the predecessor frames are for the
+ process startup code. Since we have no guarantee that the linked
+ in startup modules have any debugging information that gdb can use,
+ we need to avoid following frame pointers back into frames that might
+ have been built in the startup code, as we might get hopelessly
+ confused. However, we almost always have debugging information
+ available for main().
+
+ These variables are used to save the range of PC values which are valid
+ within the main() function and within the function containing the process
+ entry point. If we always consider the frame for main() as the outermost
+ frame when debugging user code, and the frame for the process entry
+ point function as the outermost frame when debugging startup code, then
+ all we have to do is have FRAME_CHAIN_VALID return false whenever a
+ frame's current PC is within the range specified by these variables.
+ In essence, we set "ceilings" in the frame chain beyond which we will
+ not proceed when following the frame chain back up the stack.
+
+ A nice side effect is that we can still debug startup code without
+ running off the end of the frame chain, assuming that we have usable
+ debugging information in the startup modules, and if we choose to not
+ use the block at main, or can't find it for some reason, everything
+ still works as before. And if we have no startup code debugging
+ information but we do have usable information for main(), backtraces
+ from user code don't go wandering off into the startup code.
+
+ To use this method, define your FRAME_CHAIN_VALID macro like:
+
+ #define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 \
+ && !(inside_main_func ((thisframe)->pc)) \
+ && !(inside_entry_func ((thisframe)->pc)))
+
+ and add initializations of the four scope controlling variables inside
+ the object file / debugging information processing modules. */
+
+struct entry_info
+{
+
+ /* The value we should use for this objects entry point.
+ The illegal/unknown value needs to be something other than 0, ~0
+ for instance, which is much less likely than 0. */
+
+ CORE_ADDR entry_point;
+
+ /* Start (inclusive) and end (exclusive) of function containing the
+ entry point. */
+
+ CORE_ADDR entry_func_lowpc;
+ CORE_ADDR entry_func_highpc;
+
+ /* Start (inclusive) and end (exclusive) of object file containing the
+ entry point. */
+
+ CORE_ADDR entry_file_lowpc;
+ CORE_ADDR entry_file_highpc;
+
+ /* Start (inclusive) and end (exclusive) of the user code main() function. */
+
+ CORE_ADDR main_func_lowpc;
+ CORE_ADDR main_func_highpc;
+
+};
+
+
+/* Sections in an objfile.
+
+ It is strange that we have both this notion of "sections"
+ and the one used by section_offsets. Section as used
+ here, (currently at least) means a BFD section, and the sections
+ are set up from the BFD sections in allocate_objfile.
+
+ The sections in section_offsets have their meaning determined by
+ the symbol format, and they are set up by the sym_offsets function
+ for that symbol file format.
+
+ I'm not sure this could or should be changed, however. */
+
+struct obj_section {
+ CORE_ADDR addr; /* lowest address in section */
+ CORE_ADDR endaddr; /* 1+highest address in section */
+
+ /* This field is being used for nefarious purposes by syms_from_objfile.
+ It is said to be redundant with section_offsets; it's not really being
+ used that way, however, it's some sort of hack I don't understand
+ and am not going to try to eliminate (yet, anyway). FIXME.
+
+ It was documented as "offset between (end)addr and actual memory
+ addresses", but that's not true; addr & endaddr are actual memory
+ addresses. */
+ CORE_ADDR offset;
+
+ sec_ptr sec_ptr; /* BFD section pointer */
+
+ /* Objfile this section is part of. Not currently used, but I'm sure
+ that someone will want the bfd that the sec_ptr goes with or something
+ like that before long. */
+ struct objfile *objfile;
+};
+
+/* Master structure for keeping track of each input file from which
+ gdb reads symbols. One of these is allocated for each such file we
+ access, e.g. the exec_file, symbol_file, and any shared library object
+ files. */
+
+struct objfile
+{
+
+ /* All struct objfile's are chained together by their next pointers.
+ The global variable "object_files" points to the first link in this
+ chain.
+
+ FIXME: There is a problem here if the objfile is reusable, and if
+ multiple users are to be supported. The problem is that the objfile
+ list is linked through a member of the objfile struct itself, which
+ is only valid for one gdb process. The list implementation needs to
+ be changed to something like:
+
+ struct list {struct list *next; struct objfile *objfile};
+
+ where the list structure is completely maintained separately within
+ each gdb process. */
+
+ struct objfile *next;
+
+ /* The object file's name. Malloc'd; free it if you free this struct. */
+
+ char *name;
+
+ /* Some flag bits for this objfile. */
+
+ unsigned short flags;
+
+ /* Each objfile points to a linked list of symtabs derived from this file,
+ one symtab structure for each compilation unit (source file). Each link
+ in the symtab list contains a backpointer to this objfile. */
+
+ struct symtab *symtabs;
+
+ /* Each objfile points to a linked list of partial symtabs derived from
+ this file, one partial symtab structure for each compilation unit
+ (source file). */
+
+ struct partial_symtab *psymtabs;
+
+ /* List of freed partial symtabs, available for re-use */
+
+ struct partial_symtab *free_psymtabs;
+
+ /* The object file's BFD. Can be null, in which case bfd_open (name) and
+ put the result here. */
+
+ bfd *obfd;
+
+ /* The modification timestamp of the object file, as of the last time
+ we read its symbols. */
+
+ long mtime;
+
+ /* Obstacks to hold objects that should be freed when we load a new symbol
+ table from this object file. */
+
+ struct obstack psymbol_obstack; /* Partial symbols */
+ struct obstack symbol_obstack; /* Full symbols */
+ struct obstack type_obstack; /* Types */
+
+ /* Vectors of all partial symbols read in from file. The actual data
+ is stored in the psymbol_obstack. */
+
+ struct psymbol_allocation_list global_psymbols;
+ struct psymbol_allocation_list static_psymbols;
+
+ /* Each file contains a pointer to an array of minimal symbols for all
+ global symbols that are defined within the file. The array is terminated
+ by a "null symbol", one that has a NULL pointer for the name and a zero
+ value for the address. This makes it easy to walk through the array
+ when passed a pointer to somewhere in the middle of it. There is also
+ a count of the number of symbols, which does include the terminating
+ null symbol. The array itself, as well as all the data that it points
+ to, should be allocated on the symbol_obstack for this file. */
+
+ struct minimal_symbol *msymbols;
+ int minimal_symbol_count;
+
+ /* For object file formats which don't specify fundamental types, gdb
+ can create such types. For now, it maintains a vector of pointers
+ to these internally created fundamental types on a per objfile basis,
+ however it really should ultimately keep them on a per-compilation-unit
+ basis, to account for linkage-units that consist of a number of
+ compilation units that may have different fundamental types, such as
+ linking C modules with ADA modules, or linking C modules that are
+ compiled with 32-bit ints with C modules that are compiled with 64-bit
+ ints (not inherently evil with a smarter linker). */
+
+ struct type **fundamental_types;
+
+ /* The mmalloc() malloc-descriptor for this objfile if we are using
+ the memory mapped malloc() package to manage storage for this objfile's
+ data. NULL if we are not. */
+
+ PTR md;
+
+ /* The file descriptor that was used to obtain the mmalloc descriptor
+ for this objfile. If we call mmalloc_detach with the malloc descriptor
+ we should then close this file descriptor. */
+
+ int mmfd;
+
+ /* Structure which keeps track of functions that manipulate objfile's
+ of the same type as this objfile. I.E. the function to read partial
+ symbols for example. Note that this structure is in statically
+ allocated memory, and is shared by all objfiles that use the
+ object module reader of this type. */
+
+ struct sym_fns *sf;
+
+ /* The per-objfile information about the entry point, the scope (file/func)
+ containing the entry point, and the scope of the user's main() func. */
+
+ struct entry_info ei;
+
+ /* Information about stabs. Will be filled in with a dbx_symfile_info
+ struct by those readers that need it. */
+
+ PTR sym_stab_info;
+
+ /* Hook for information for use by the symbol reader (currently used
+ for information shared by sym_init and sym_read). It is
+ typically a pointer to malloc'd memory. The symbol reader's finish
+ function is responsible for freeing the memory thusly allocated. */
+
+ PTR sym_private;
+
+ /* Hook for target-architecture-specific information. This must
+ point to memory allocated on one of the obstacks in this objfile,
+ so that it gets freed automatically when reading a new object
+ file. */
+
+ PTR obj_private;
+
+ /* Set of relocation offsets to apply to each section.
+ Currently on the psymbol_obstack (which makes no sense, but I'm
+ not sure it's harming anything).
+
+ These offsets indicate that all symbols (including partial and
+ minimal symbols) which have been read have been relocated by this
+ much. Symbols which are yet to be read need to be relocated by
+ it. */
+
+ struct section_offsets *section_offsets;
+ int num_sections;
+
+ /* set of section begin and end addresses used to map pc addresses
+ into sections. Currently on the psymbol_obstack (which makes no
+ sense, but I'm not sure it's harming anything). */
+
+ struct obj_section
+ *sections,
+ *sections_end;
+};
+
+/* Defines for the objfile flag word. */
+
+/* Gdb can arrange to allocate storage for all objects related to a
+ particular objfile in a designated section of it's address space,
+ managed at a low level by mmap() and using a special version of
+ malloc that handles malloc/free/realloc on top of the mmap() interface.
+ This allows the "internal gdb state" for a particular objfile to be
+ dumped to a gdb state file and subsequently reloaded at a later time. */
+
+#define OBJF_MAPPED (1 << 0) /* Objfile data is mmap'd */
+
+/* When using mapped/remapped predigested gdb symbol information, we need
+ a flag that indicates that we have previously done an initial symbol
+ table read from this particular objfile. We can't just look for the
+ absence of any of the three symbol tables (msymbols, psymtab, symtab)
+ because if the file has no symbols for example, none of these will
+ exist. */
+
+#define OBJF_SYMS (1 << 1) /* Have tried to read symbols */
+
+/* The object file that the main symbol table was loaded from (e.g. the
+ argument to the "symbol-file" or "file" command). */
+
+extern struct objfile *symfile_objfile;
+
+/* When we need to allocate a new type, we need to know which type_obstack
+ to allocate the type on, since there is one for each objfile. The places
+ where types are allocated are deeply buried in function call hierarchies
+ which know nothing about objfiles, so rather than trying to pass a
+ particular objfile down to them, we just do an end run around them and
+ set current_objfile to be whatever objfile we expect to be using at the
+ time types are being allocated. For instance, when we start reading
+ symbols for a particular objfile, we set current_objfile to point to that
+ objfile, and when we are done, we set it back to NULL, to ensure that we
+ never put a type someplace other than where we are expecting to put it.
+ FIXME: Maybe we should review the entire type handling system and
+ see if there is a better way to avoid this problem. */
+
+extern struct objfile *current_objfile;
+
+/* All known objfiles are kept in a linked list. This points to the
+ root of this list. */
+
+extern struct objfile *object_files;
+
+/* Declarations for functions defined in objfiles.c */
+
+extern struct objfile *
+allocate_objfile PARAMS ((bfd *, int));
+
+extern void
+unlink_objfile PARAMS ((struct objfile *));
+
+extern void
+free_objfile PARAMS ((struct objfile *));
+
+extern void
+free_all_objfiles PARAMS ((void));
+
+extern void
+objfile_relocate PARAMS ((struct objfile *, struct section_offsets *));
+
+extern int
+have_partial_symbols PARAMS ((void));
+
+extern int
+have_full_symbols PARAMS ((void));
+
+/* Functions for dealing with the minimal symbol table, really a misc
+ address<->symbol mapping for things we don't have debug symbols for. */
+
+extern int
+have_minimal_symbols PARAMS ((void));
+
+extern struct obj_section *
+find_pc_section PARAMS((CORE_ADDR pc));
+
+/* Traverse all object files. ALL_OBJFILES_SAFE works even if you delete
+ the objfile during the traversal. */
+
+#define ALL_OBJFILES(obj) \
+ for ((obj) = object_files; (obj) != NULL; (obj) = (obj)->next)
+
+#define ALL_OBJFILES_SAFE(obj,nxt) \
+ for ((obj) = object_files; \
+ (obj) != NULL? ((nxt)=(obj)->next,1) :0; \
+ (obj) = (nxt))
+
+
+/* Traverse all symtabs in one objfile. */
+
+#define ALL_OBJFILE_SYMTABS(objfile, s) \
+ for ((s) = (objfile) -> symtabs; (s) != NULL; (s) = (s) -> next)
+
+/* Traverse all psymtabs in one objfile. */
+
+#define ALL_OBJFILE_PSYMTABS(objfile, p) \
+ for ((p) = (objfile) -> psymtabs; (p) != NULL; (p) = (p) -> next)
+
+/* Traverse all minimal symbols in one objfile. */
+
+#define ALL_OBJFILE_MSYMBOLS(objfile, m) \
+ for ((m) = (objfile) -> msymbols; SYMBOL_NAME(m) != NULL; (m)++)
+
+
+/* Traverse all symtabs in all objfiles. */
+
+#define ALL_SYMTABS(objfile, s) \
+ ALL_OBJFILES (objfile) \
+ ALL_OBJFILE_SYMTABS (objfile, s)
+
+/* Traverse all psymtabs in all objfiles. */
+
+#define ALL_PSYMTABS(objfile, p) \
+ ALL_OBJFILES (objfile) \
+ ALL_OBJFILE_PSYMTABS (objfile, p)
+
+/* Traverse all minimal symbols in all objfiles. */
+
+#define ALL_MSYMBOLS(objfile, m) \
+ ALL_OBJFILES (objfile) \
+ if ((objfile)->msymbols) \
+ ALL_OBJFILE_MSYMBOLS (objfile, m)
+
+#endif /* !defined (OBJFILES_H) */
diff --git a/gnu/usr.bin/gdb/obstack.h b/gnu/usr.bin/gdb/gdb/obstack.h
index 27c017e2f253..689f14855fed 100644
--- a/gnu/usr.bin/gdb/obstack.h
+++ b/gnu/usr.bin/gdb/gdb/obstack.h
@@ -1,25 +1,19 @@
/* obstack.h - object stack macros
- Copyright (C) 1988 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992 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
+under the terms of the GNU Library General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
later version.
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.
+GNU Library General Public License for more details.
-You should have received a copy of the GNU General Public License
+You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
-Foundation, 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! */
-
+Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Summary:
@@ -46,8 +40,8 @@ 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 "facist pig with a read-only mind"
-[Gosper's immortal quote from HAKMEM item 154, out of context] you
+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.
@@ -65,7 +59,7 @@ 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 aymbol in the chunk you just
+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.
@@ -82,8 +76,8 @@ 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 beggining of the new larger chunk. We then carry on
-accreting characters to the end of the object as we normaly would.
+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
@@ -98,7 +92,7 @@ Summary:
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
+ Because of the way we do it, you can `unwind' an obstack
back to a previous state. (You may remove objects much
as you would with a stack.)
*/
@@ -121,6 +115,32 @@ Summary:
#define __INT_TO_PTR(P) ((P) + (char *)0)
#endif
+/* We need the type of the resulting object. In ANSI C it is ptrdiff_t
+ but in traditional C it is usually long. If we are in ANSI C and
+ don't already have ptrdiff_t get it. */
+
+#if defined (__STDC__) && ! defined (offsetof)
+#if defined (__GNUC__) && defined (IN_GCC)
+/* On Next machine, the system's stddef.h screws up if included
+ after we have defined just ptrdiff_t, so include all of gstddef.h.
+ Otherwise, define just ptrdiff_t, which is all we need. */
+#ifndef __NeXT__
+#define __need_ptrdiff_t
+#endif
+
+/* While building GCC, the stddef.h that goes with GCC has this name. */
+#include "gstddef.h"
+#else
+#include <stddef.h>
+#endif
+#endif
+
+#ifdef __STDC__
+#define PTR_INT_TYPE ptrdiff_t
+#else
+#define PTR_INT_TYPE long
+#endif
+
struct _obstack_chunk /* Lives at front of each chunk. */
{
char *limit; /* 1 past end of this chunk */
@@ -135,11 +155,33 @@ struct obstack /* control current object in current 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. */
+ PTR_INT_TYPE temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
void (*freefun) (); /* User's function to free a chunk. */
+ char *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+ unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
+ unsigned maybe_empty_object:1;/* There is a possibility that the current
+ chunk contains a zero-length object. This
+ prevents freeing the chunk if we allocate
+ a bigger chunk to replace it. */
};
+
+/* Declare the external functions we use; they are in obstack.c. */
+
+#ifdef __STDC__
+extern void _obstack_newchunk (struct obstack *, int);
+extern void _obstack_free (struct obstack *, void *);
+extern void _obstack_begin (struct obstack *, int, int,
+ void *(*) (), void (*) ());
+extern void _obstack_begin_1 (struct obstack *, int, int,
+ void *(*) (), void (*) (), void *);
+#else
+extern void _obstack_newchunk ();
+extern void _obstack_free ();
+extern void _obstack_begin ();
+extern void _obstack_begin_1 ();
+#endif
#ifdef __STDC__
@@ -161,6 +203,8 @@ 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);
@@ -168,6 +212,8 @@ 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);
@@ -199,16 +245,35 @@ int obstack_chunk_size (struct obstack *obstack);
#define obstack_alignment_mask(h) ((h)->alignment_mask)
#define obstack_init(h) \
- _obstack_begin ((h), 0, 0, obstack_chunk_alloc, obstack_chunk_free)
+ _obstack_begin ((h), 0, 0, \
+ (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
#define obstack_begin(h, size) \
- _obstack_begin ((h), (size), 0, obstack_chunk_alloc, obstack_chunk_free)
+ _obstack_begin ((h), (size), 0, \
+ (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
+
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+ _obstack_begin ((h), (size), (alignment), \
+ (void *(*) ()) (chunkfun), (void (*) ()) (freefun))
+
+#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+ _obstack_begin_1 ((h), (size), (alignment), \
+ (void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg))
+
+#define obstack_chunkfun(h, newchunkfun) \
+ ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun))
+
+#define obstack_freefun(h, newfreefun) \
+ ((h) -> freefun = (void (*)()) (newfreefun))
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
#if defined (__GNUC__) && defined (__STDC__)
+#if __GNUC__ < 2
+#define __extension__
+#endif
/* For GNU C, if not -traditional,
we can define these macros to compute all args only once
@@ -216,118 +281,169 @@ int obstack_chunk_size (struct obstack *obstack);
Also, we can avoid using the `temp' slot, to make faster code. */
#define obstack_object_size(OBSTACK) \
+ __extension__ \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->next_free - __o->object_base); })
#define obstack_room(OBSTACK) \
+ __extension__ \
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->chunk_limit - __o->next_free); })
+/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
+ so that we can avoid having void expressions
+ in the arms of the conditional expression.
+ Casting the third operand to void was tried before,
+ but some compilers won't accept it. */
#define obstack_grow(OBSTACK,where,length) \
+__extension__ \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len > __o->chunk_limit) \
- ? _obstack_newchunk (__o, __len) : 0); \
+ ? (_obstack_newchunk (__o, __len), 0) : 0); \
bcopy (where, __o->next_free, __len); \
__o->next_free += __len; \
(void) 0; })
#define obstack_grow0(OBSTACK,where,length) \
+__extension__ \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
((__o->next_free + __len + 1 > __o->chunk_limit) \
- ? _obstack_newchunk (__o, __len + 1) : 0), \
+ ? (_obstack_newchunk (__o, __len + 1), 0) : 0), \
bcopy (where, __o->next_free, __len), \
__o->next_free += __len, \
*(__o->next_free)++ = 0; \
(void) 0; })
#define obstack_1grow(OBSTACK,datum) \
+__extension__ \
({ struct obstack *__o = (OBSTACK); \
((__o->next_free + 1 > __o->chunk_limit) \
- ? _obstack_newchunk (__o, 1) : 0), \
+ ? (_obstack_newchunk (__o, 1), 0) : 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) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + sizeof (void *) > __o->chunk_limit) \
+ ? (_obstack_newchunk (__o, sizeof (void *)), 0) : 0), \
+ *((void **)__o->next_free)++ = ((void *)datum); \
+ (void) 0; })
+
+#define obstack_int_grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ ((__o->next_free + sizeof (int) > __o->chunk_limit) \
+ ? (_obstack_newchunk (__o, sizeof (int)), 0) : 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) \
+__extension__ \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
- ((__o->next_free + __len > __o->chunk_limit) \
- ? _obstack_newchunk (__o, __len) : 0); \
+ ((__o->chunk_limit - __o->next_free < __len) \
+ ? (_obstack_newchunk (__o, __len), 0) : 0); \
__o->next_free += __len; \
(void) 0; })
#define obstack_alloc(OBSTACK,length) \
+__extension__ \
({ struct obstack *__h = (OBSTACK); \
obstack_blank (__h, (length)); \
obstack_finish (__h); })
#define obstack_copy(OBSTACK,where,length) \
+__extension__ \
({ struct obstack *__h = (OBSTACK); \
obstack_grow (__h, (where), (length)); \
obstack_finish (__h); })
#define obstack_copy0(OBSTACK,where,length) \
+__extension__ \
({ struct obstack *__h = (OBSTACK); \
obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); })
+/* The local variable is named __o1 to avoid a name conflict
+ when obstack_blank is called. */
#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; \
+__extension__ \
+({ struct obstack *__o1 = (OBSTACK); \
+ void *value = (void *) __o1->object_base; \
+ if (__o1->next_free == value) \
+ __o1->maybe_empty_object = 1; \
+ __o1->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
+ & ~ (__o1->alignment_mask)); \
+ ((__o1->next_free - (char *)__o1->chunk \
+ > __o1->chunk_limit - (char *)__o1->chunk) \
+ ? (__o1->next_free = __o1->chunk_limit) : 0); \
+ __o1->object_base = __o1->next_free; \
value; })
#define obstack_free(OBSTACK, OBJ) \
+__extension__ \
({ struct obstack *__o = (OBSTACK); \
void *__obj = (OBJ); \
- if (__obj >= (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
+ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
__o->next_free = __o->object_base = __obj; \
else (obstack_free) (__o, __obj); })
#else /* not __GNUC__ or not __STDC__ */
-/* The non-GNU macros copy the obstack-pointer into this global variable
- to avoid multiple evaluation. */
-
-extern struct obstack *_obstack;
-
#define obstack_object_size(h) \
- (unsigned) (_obstack = (h), (h)->next_free - (h)->object_base)
+ (unsigned) ((h)->next_free - (h)->object_base)
#define obstack_room(h) \
- (unsigned) (_obstack = (h), (h)->chunk_limit - (h)->next_free)
+ (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), \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 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), \
+ ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 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), \
+ ? (_obstack_newchunk ((h), 1), 0) : 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) : 0), \
+ *((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum))
+
+#define obstack_int_grow(h,datum) \
+( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
+ *((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((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)->next_free + (h)->temp > (h)->chunk_limit) \
- ? _obstack_newchunk ((h), (h)->temp) : 0), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp) \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
(h)->next_free += (h)->temp)
#define obstack_alloc(h,length) \
@@ -340,7 +456,10 @@ extern struct obstack *_obstack;
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
#define obstack_finish(h) \
-( (h)->temp = __PTR_TO_INT ((h)->object_base), \
+( ((h)->next_free == (h)->object_base \
+ ? (((h)->maybe_empty_object = 1), 0) \
+ : 0), \
+ (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)), \
@@ -353,20 +472,19 @@ extern struct obstack *_obstack;
#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)\
+ (((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)))
+ : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 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)\
+ (((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)))
+ : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0)))
#endif
#endif /* not __GNUC__ or not __STDC__ */
#endif /* not __OBSTACKS__ */
-
diff --git a/gnu/usr.bin/gdb/gdb/parse.c b/gnu/usr.bin/gdb/gdb/parse.c
new file mode 100644
index 000000000000..08f2b7e67484
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/parse.c
@@ -0,0 +1,827 @@
+/* Parse expressions for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+ Modified from expread.y by the Department of Computer Science at the
+ State University of New York at Buffalo, 1991.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Parse an 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 "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "frame.h"
+#include "expression.h"
+#include "value.h"
+#include "command.h"
+#include "language.h"
+#include "parser-defs.h"
+
+static void
+free_funcalls PARAMS ((void));
+
+static void
+prefixify_expression PARAMS ((struct expression *));
+
+static int
+length_of_subexp PARAMS ((struct expression *, int));
+
+static void
+prefixify_subexp PARAMS ((struct expression *, struct expression *, int, int));
+
+/* 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;
+ };
+
+static struct funcall *funcall_chain;
+
+/* Assign machine-independent names to certain registers
+ (unless overridden by the REGISTER_NAMES table) */
+
+#ifdef NO_STD_REGS
+unsigned num_std_regs = 0;
+struct std_regs std_regs[1];
+#else
+struct std_regs 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
+
+};
+
+unsigned num_std_regs = (sizeof std_regs / sizeof std_regs[0]);
+
+#endif
+
+
+/* Begin counting arguments for a function call,
+ saving the data about any containing call. */
+
+void
+start_arglist ()
+{
+ register struct funcall *new;
+
+ 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. */
+
+int
+end_arglist ()
+{
+ register int val = arglist_len;
+ register struct funcall *call = funcall_chain;
+ funcall_chain = call->next;
+ arglist_len = call->arglist_len;
+ free ((PTR)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 ((PTR)call);
+ }
+}
+
+/* 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 */
+
+void
+write_exp_elt (expelt)
+ union exp_element expelt;
+{
+ if (expout_ptr >= expout_size)
+ {
+ expout_size *= 2;
+ expout = (struct expression *)
+ xrealloc ((char *) expout, sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size));
+ }
+ expout->elts[expout_ptr++] = expelt;
+}
+
+void
+write_exp_elt_opcode (expelt)
+ enum exp_opcode expelt;
+{
+ union exp_element tmp;
+
+ tmp.opcode = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_sym (expelt)
+ struct symbol *expelt;
+{
+ union exp_element tmp;
+
+ tmp.symbol = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_block (b)
+ struct block *b;
+{
+ union exp_element tmp;
+ tmp.block = b;
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_longcst (expelt)
+ LONGEST expelt;
+{
+ union exp_element tmp;
+
+ tmp.longconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_dblcst (expelt)
+ double expelt;
+{
+ union exp_element tmp;
+
+ tmp.doubleconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_type (expelt)
+ struct type *expelt;
+{
+ union exp_element tmp;
+
+ tmp.type = expelt;
+
+ write_exp_elt (tmp);
+}
+
+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.
+
+ String constants are stored by first writing an expression element
+ that contains the length of the string, then stuffing the string
+ constant itself into however many expression elements are needed
+ to hold it, and then writing another expression element that contains
+ the length of the string. I.E. an expression element at each end of
+ the string records the string length, so you can skip over the
+ expression elements containing the actual string bytes from either
+ end of the string. Note that this also allows gdb to handle
+ strings with embedded null bytes, as is required for some languages.
+
+ Don't be fooled by the fact that the string is null byte terminated,
+ this is strictly for the convenience of debugging gdb itself. Gdb
+ Gdb does not depend up the string being null terminated, since the
+ actual length is recorded in expression elements at each end of the
+ string. The null byte is taken into consideration when computing how
+ many expression elements are required to hold the string constant, of
+ course. */
+
+
+void
+write_exp_string (str)
+ struct stoken str;
+{
+ register int len = str.length;
+ register int lenelt;
+ register char *strdata;
+
+ /* Compute the number of expression elements required to hold the string
+ (including a null byte terminator), along with one expression element
+ at each end to record the actual string length (not including the
+ null byte terminator). */
+
+ lenelt = 2 + BYTES_TO_EXP_ELEM (len + 1);
+
+ /* Ensure that we have enough available expression elements to store
+ everything. */
+
+ if ((expout_ptr + lenelt) >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
+ expout = (struct expression *)
+ xrealloc ((char *) expout, (sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size)));
+ }
+
+ /* Write the leading length expression element (which advances the current
+ expression element index), then write the string constant followed by a
+ terminating null byte, and then write the trailing length expression
+ element. */
+
+ write_exp_elt_longcst ((LONGEST) len);
+ strdata = (char *) &expout->elts[expout_ptr];
+ memcpy (strdata, str.ptr, len);
+ *(strdata + len) = '\0';
+ expout_ptr += lenelt - 2;
+ write_exp_elt_longcst ((LONGEST) len);
+}
+
+/* Add a bitstring constant to the end of the expression.
+
+ Bitstring constants are stored by first writing an expression element
+ that contains the length of the bitstring (in bits), then stuffing the
+ bitstring constant itself into however many expression elements are
+ needed to hold it, and then writing another expression element that
+ contains the length of the bitstring. I.E. an expression element at
+ each end of the bitstring records the bitstring length, so you can skip
+ over the expression elements containing the actual bitstring bytes from
+ either end of the bitstring. */
+
+void
+write_exp_bitstring (str)
+ struct stoken str;
+{
+ register int bits = str.length; /* length in bits */
+ register int len = (bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ register int lenelt;
+ register char *strdata;
+
+ /* Compute the number of expression elements required to hold the bitstring,
+ along with one expression element at each end to record the actual
+ bitstring length in bits. */
+
+ lenelt = 2 + BYTES_TO_EXP_ELEM (len);
+
+ /* Ensure that we have enough available expression elements to store
+ everything. */
+
+ if ((expout_ptr + lenelt) >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
+ expout = (struct expression *)
+ xrealloc ((char *) expout, (sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size)));
+ }
+
+ /* Write the leading length expression element (which advances the current
+ expression element index), then write the bitstring constant, and then
+ write the trailing length expression element. */
+
+ write_exp_elt_longcst ((LONGEST) bits);
+ strdata = (char *) &expout->elts[expout_ptr];
+ memcpy (strdata, str.ptr, len);
+ expout_ptr += lenelt - 2;
+ write_exp_elt_longcst ((LONGEST) bits);
+}
+
+/* Return a null-terminated temporary copy of the name
+ of a string token. */
+
+char *
+copy_name (token)
+ struct stoken token;
+{
+ memcpy (namecopy, token.ptr, token.length);
+ namecopy[token.length] = 0;
+ return namecopy;
+}
+
+/* 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_expression (expr)
+ register struct expression *expr;
+{
+ register int len =
+ sizeof (struct expression) + EXP_ELEM_TO_BYTES (expr->nelts);
+ register struct expression *temp;
+ register int inpos = expr->nelts, outpos = 0;
+
+ temp = (struct expression *) alloca (len);
+
+ /* Copy the original expression into temp. */
+ memcpy (temp, expr, 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 < 1)
+ error ("?error in length_of_subexp");
+
+ i = (int) expr->elts[endpos - 1].opcode;
+
+ switch (i)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 5 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ case OP_VAR_VALUE:
+ oplen = 4;
+ break;
+
+ case OP_TYPE:
+ case OP_BOOL:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_FUNCALL:
+ oplen = 3;
+ args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
+ break;
+
+ case UNOP_MAX:
+ case UNOP_MIN:
+ oplen = 3;
+ break;
+
+ case BINOP_VAL:
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case UNOP_ABS:
+ case UNOP_CAP:
+ case UNOP_CHR:
+ case UNOP_FLOAT:
+ case UNOP_HIGH:
+ case UNOP_ODD:
+ case UNOP_ORD:
+ case UNOP_TRUNC:
+ oplen = 1;
+ args = 1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ /* fall through */
+ case OP_M2_STRING:
+ case OP_STRING:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_BITSTRING:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = (oplen + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen);
+ break;
+
+ case OP_ARRAY:
+ oplen = 4;
+ args = longest_to_int (expr->elts[endpos - 2].longconst);
+ args -= longest_to_int (expr->elts[endpos - 3].longconst);
+ args += 1;
+ break;
+
+ case TERNOP_COND:
+ args = 3;
+ break;
+
+ /* Modula-2 */
+ case MULTI_SUBSCRIPT:
+ oplen=3;
+ args = 1 + longest_to_int (expr->elts[endpos- 2].longconst);
+ 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 = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = 5 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ case OP_VAR_VALUE:
+ oplen = 4;
+ break;
+
+ case OP_TYPE:
+ case OP_BOOL:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_FUNCALL:
+ oplen = 3;
+ args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
+ break;
+
+ case UNOP_MIN:
+ case UNOP_MAX:
+ oplen = 3;
+ break;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case UNOP_ABS:
+ case UNOP_CAP:
+ case UNOP_CHR:
+ case UNOP_FLOAT:
+ case UNOP_HIGH:
+ case UNOP_ODD:
+ case UNOP_ORD:
+ case UNOP_TRUNC:
+ oplen=1;
+ args=1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ /* fall through */
+ case OP_M2_STRING:
+ case OP_STRING:
+ oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_BITSTRING:
+ oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = (oplen + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen);
+ break;
+
+ case OP_ARRAY:
+ oplen = 4;
+ args = longest_to_int (inexpr->elts[inend - 2].longconst);
+ args -= longest_to_int (inexpr->elts[inend - 3].longconst);
+ args += 1;
+ break;
+
+ case TERNOP_COND:
+ args = 3;
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* Modula-2 */
+ case MULTI_SUBSCRIPT:
+ oplen=3;
+ args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
+ 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;
+ memcpy (&outexpr->elts[outbeg], &inexpr->elts[inend],
+ EXP_ELEM_TO_BYTES (oplen));
+ 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;
+ }
+}
+
+/* This page contains the two entry points to this file. */
+
+/* Read an 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_exp_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) + EXP_ELEM_TO_BYTES (expout_size));
+ expout->language_defn = current_language;
+ make_cleanup (free_current_contents, &expout);
+
+ if (current_language->la_parser ())
+ current_language->la_error (NULL);
+
+ discard_cleanups (old_chain);
+
+ /* Record the actual number of expression elements, and then
+ reallocate the expression memory so that we free up any
+ excess elements. */
+
+ expout->nelts = expout_ptr;
+ expout = (struct expression *)
+ xrealloc ((char *) expout,
+ sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_ptr));;
+
+ /* Convert expression from postfix form as generated by yacc
+ parser, to a prefix form. */
+
+ DUMP_EXPRESSION (expout, stdout, "before conversion to prefix form");
+ prefixify_expression (expout);
+ DUMP_EXPRESSION (expout, stdout, "after conversion to prefix form");
+
+ *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_expression (string)
+ char *string;
+{
+ register struct expression *exp;
+ exp = parse_exp_1 (&string, 0, 0);
+ if (*string)
+ error ("Junk after end of expression.");
+ return exp;
+}
+
+/* Stuff for maintaining a stack of types. Currently just used by C, but
+ probably useful for any language which declares its types "backwards". */
+
+void
+push_type (tp)
+ enum type_pieces tp;
+{
+ if (type_stack_depth == type_stack_size)
+ {
+ type_stack_size *= 2;
+ type_stack = (union type_stack_elt *)
+ xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
+ }
+ type_stack[type_stack_depth++].piece = tp;
+}
+
+void
+push_type_int (n)
+ int n;
+{
+ if (type_stack_depth == type_stack_size)
+ {
+ type_stack_size *= 2;
+ type_stack = (union type_stack_elt *)
+ xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
+ }
+ type_stack[type_stack_depth++].int_val = n;
+}
+
+enum type_pieces
+pop_type ()
+{
+ if (type_stack_depth)
+ return type_stack[--type_stack_depth].piece;
+ return tp_end;
+}
+
+int
+pop_type_int ()
+{
+ if (type_stack_depth)
+ return type_stack[--type_stack_depth].int_val;
+ /* "Can't happen". */
+ return 0;
+}
+
+/* Pop the type stack and return the type which corresponds to FOLLOW_TYPE
+ as modified by all the stuff on the stack. */
+struct type *
+follow_types (follow_type)
+ struct type *follow_type;
+{
+ int done = 0;
+ int array_size;
+ struct type *range_type;
+
+ 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 = pop_type_int ();
+ if (array_size != -1)
+ {
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_int, 0,
+ array_size - 1);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ }
+ else
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_function:
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ return follow_type;
+}
+
+void
+_initialize_parse ()
+{
+ type_stack_size = 80;
+ type_stack_depth = 0;
+ type_stack = (union type_stack_elt *)
+ xmalloc (type_stack_size * sizeof (*type_stack));
+}
diff --git a/gnu/usr.bin/gdb/gdb/parser-defs.h b/gnu/usr.bin/gdb/gdb/parser-defs.h
new file mode 100644
index 000000000000..5c8710e4e6e2
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/parser-defs.h
@@ -0,0 +1,188 @@
+/* Parser definitions for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+ Modified from expread.y by the Department of Computer Science at the
+ State University of New York at Buffalo.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (PARSER_DEFS_H)
+#define PARSER_DEFS_H 1
+
+struct std_regs {
+ char *name;
+ int regnum;
+};
+
+extern struct std_regs std_regs[];
+extern unsigned num_std_regs;
+
+struct expression *expout;
+int expout_size;
+int expout_ptr;
+
+/* If this is nonzero, this block is used as the lexical context
+ for symbol names. */
+
+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. */
+int arglist_len;
+
+/* A string token, either a char-string or bit-string. Char-strings are
+ used, for example, for the names of symbols. */
+
+struct stoken
+ {
+ /* Pointer to first byte of char-string or first bit of bit-string */
+ char *ptr;
+ /* Length of string in bytes for char-string or bits for bit-string */
+ 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};
+/* The stack can contain either an enum type_pieces or an int. */
+union type_stack_elt {
+ enum type_pieces piece;
+ int int_val;
+};
+union type_stack_elt *type_stack;
+int type_stack_depth, type_stack_size;
+
+extern void
+write_exp_elt PARAMS ((union exp_element));
+
+extern void
+write_exp_elt_opcode PARAMS ((enum exp_opcode));
+
+extern void
+write_exp_elt_sym PARAMS ((struct symbol *));
+
+extern void
+write_exp_elt_longcst PARAMS ((LONGEST));
+
+extern void
+write_exp_elt_dblcst PARAMS ((double));
+
+extern void
+write_exp_elt_type PARAMS ((struct type *));
+
+extern void
+write_exp_elt_intern PARAMS ((struct internalvar *));
+
+extern void
+write_exp_string PARAMS ((struct stoken));
+
+extern void
+write_exp_bitstring PARAMS ((struct stoken));
+
+extern void
+start_arglist PARAMS ((void));
+
+extern int
+end_arglist PARAMS ((void));
+
+extern char *
+copy_name PARAMS ((struct stoken));
+
+extern void
+push_type PARAMS ((enum type_pieces));
+
+extern void
+push_type_int PARAMS ((int));
+
+extern enum type_pieces
+pop_type PARAMS ((void));
+
+extern int
+pop_type_int PARAMS ((void));
+
+extern struct type *follow_types PARAMS ((struct type *));
+
+/* During parsing of a C expression, the pointer to the next character
+ is in this variable. */
+
+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. */
+
+char *namecopy;
+
+/* Current depth in parentheses within the expression. */
+
+int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses). */
+
+int comma_terminates;
+
+/* These codes indicate operator precedences for expression printing,
+ 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_LOGICAL_OR,
+ PREC_LOGICAL_AND, PREC_BITWISE_IOR, PREC_BITWISE_AND, PREC_BITWISE_XOR,
+ 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;
+};
+
+#endif /* PARSER_DEFS_H */
diff --git a/gnu/usr.bin/gdb/gdb/partial-stab.h b/gnu/usr.bin/gdb/gdb/partial-stab.h
new file mode 100644
index 000000000000..3be0be618873
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/partial-stab.h
@@ -0,0 +1,618 @@
+/* Shared code to pre-read a stab (dbx-style), when building a psymtab.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* The following need to be defined:
+ SET_NAMESTRING() --Set namestring to name of symbol.
+ CUR_SYMBOL_TYPE --Type code of current symbol.
+ CUR_SYMBOL_VALUE --Value field of current symbol. May be adjusted here.
+ */
+
+/* End of macro definitions, now let's handle them symbols! */
+
+ switch (CUR_SYMBOL_TYPE)
+ {
+ char *p;
+ /*
+ * Standard, external, non-debugger, symbols
+ */
+
+ case N_TEXT | N_EXT:
+ case N_NBTEXT | N_EXT:
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ goto record_it;
+
+ case N_DATA | N_EXT:
+ case N_NBDATA | N_EXT:
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ goto record_it;
+
+ case N_BSS:
+ case N_BSS | N_EXT:
+ case N_NBBSS | N_EXT:
+ case N_SETV | N_EXT: /* FIXME, is this in BSS? */
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ goto record_it;
+
+ case N_ABS | N_EXT:
+ record_it:
+#ifdef DBXREAD_ONLY
+ SET_NAMESTRING();
+
+ bss_ext_symbol:
+ record_minimal_symbol (namestring, CUR_SYMBOL_VALUE,
+ CUR_SYMBOL_TYPE, objfile); /* Always */
+#endif /* DBXREAD_ONLY */
+ 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. Sequents throw
+ in another wrinkle -- they renumbered N_FN. */
+
+ case N_FN:
+ case N_FN_SEQ:
+ case N_TEXT:
+#ifdef DBXREAD_ONLY
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ SET_NAMESTRING();
+ if ((namestring[0] == '-' && namestring[1] == 'l')
+ || (namestring [(nsl = strlen (namestring)) - 1] == 'o'
+ && namestring [nsl - 2] == '.')
+#ifdef GDB_TARGET_IS_HPPA
+ /* some cooperation from gcc to get around ld stupidity */
+ || (namestring[0] == 'e' && STREQ (namestring, "end_file."))
+#endif
+ )
+ {
+#ifndef GDB_TARGET_IS_HPPA
+ if (objfile -> ei.entry_point < CUR_SYMBOL_VALUE &&
+ objfile -> ei.entry_point >= last_o_file_start)
+ {
+ objfile -> ei.entry_file_lowpc = last_o_file_start;
+ objfile -> ei.entry_file_highpc = CUR_SYMBOL_VALUE;
+ }
+#endif
+ if (past_first_source_file && pst
+ /* The gould NP1 uses low values for .o and -l symbols
+ which are not the address. */
+ && CUR_SYMBOL_VALUE >= pst->textlow)
+ {
+ END_PSYMTAB (pst, psymtab_include_list, includes_used,
+ symnum * symbol_size, CUR_SYMBOL_VALUE,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ else
+ past_first_source_file = 1;
+ last_o_file_start = CUR_SYMBOL_VALUE;
+ }
+ else
+ goto record_it;
+#endif /* DBXREAD_ONLY */
+ continue;
+
+ case N_DATA:
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ goto record_it;
+
+ case N_UNDF | N_EXT:
+#ifdef DBXREAD_ONLY
+ if (CUR_SYMBOL_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. */
+ }
+ CUR_SYMBOL_TYPE ^= (N_BSS^N_UNDF); /* Define it as a bss-symbol */
+ CUR_SYMBOL_VALUE = reladdr;
+ goto bss_ext_symbol;
+ }
+#endif /* DBXREAD_ONLY */
+ continue; /* Just undefined, not COMMON */
+
+ case N_UNDF:
+#ifdef DBXREAD_ONLY
+ if (processing_acc_compilation && bufp->n_strx == 1) {
+ /* Deal with relative offsets in the string table
+ used in ELF+STAB under Solaris. If we want to use the
+ n_strx field, which contains the name of the file,
+ we must adjust file_string_table_offset *before* calling
+ SET_NAMESTRING(). */
+ past_first_source_file = 1;
+ file_string_table_offset = next_file_string_table_offset;
+ next_file_string_table_offset =
+ file_string_table_offset + bufp->n_value;
+ if (next_file_string_table_offset < file_string_table_offset)
+ error ("string table offset backs up at %d", symnum);
+ /* FIXME -- replace error() with complaint. */
+ continue;
+ }
+#endif /* DBXREAD_ONLY */
+ continue;
+
+ /* Lots of symbol types we can just ignore. */
+
+ case N_ABS:
+ 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;
+ static int prev_so_symnum = -10;
+ static int first_so_symnum;
+ char *p;
+
+ valu = CUR_SYMBOL_VALUE + ANOFFSET (section_offsets, SECT_OFF_TEXT);
+
+ past_first_source_file = 1;
+
+ if (prev_so_symnum != symnum - 1)
+ { /* Here if prev stab wasn't N_SO */
+ first_so_symnum = symnum;
+
+ if (pst)
+ {
+ END_PSYMTAB (pst, psymtab_include_list, includes_used,
+ symnum * symbol_size, valu,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ }
+
+ prev_so_symnum = symnum;
+
+ /* End the current partial symtab and start a new one */
+
+ SET_NAMESTRING();
+
+ /* Some compilers (including gcc) emit a pair of initial N_SOs.
+ The first one is a directory name; the second the file name.
+ If pst exists, is empty, and has a filename ending in '/',
+ we assume the previous N_SO was a directory name. */
+
+ p = strrchr (namestring, '/');
+ if (p && *(p+1) == '\000')
+ continue; /* Simply ignore directory name SOs */
+
+ /* Some other compilers (C++ ones in particular) emit useless
+ SOs for non-existant .c files. We ignore all subsequent SOs that
+ immediately follow the first. */
+
+ if (!pst)
+ pst = START_PSYMTAB (objfile, section_offsets,
+ namestring, valu,
+ first_so_symnum * symbol_size,
+ objfile -> global_psymbols.next,
+ objfile -> static_psymbols.next);
+ continue;
+ }
+
+ case N_BINCL:
+#ifdef DBXREAD_ONLY
+ /* 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, CUR_SYMBOL_VALUE);
+
+ /* Mark down an include file in the current psymtab */
+
+ goto record_include_file;
+
+#else /* DBXREAD_ONLY */
+ continue;
+#endif
+
+ 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 -- either the main
+ source file, or a previously included file.
+
+ This seems to be a lot of time to be spending on N_SOL, but
+ things like "break c-exp.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). */
+ if (pst && STREQ (namestring, pst->filename))
+ continue;
+ {
+ register int i;
+ for (i = 0; i < includes_used; i++)
+ if (STREQ (namestring, psymtab_include_list[i]))
+ {
+ i = -1;
+ break;
+ }
+ if (i == -1)
+ continue;
+ }
+
+#ifdef DBXREAD_ONLY
+ record_include_file:
+#endif
+
+ 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 *));
+ memcpy ((PTR)psymtab_include_list, (PTR)orig,
+ includes_used * sizeof (char *));
+ }
+ continue;
+
+ case N_LSYM: /* Typedef or automatic variable. */
+ case N_STSYM: /* Data seg var -- static */
+ case N_LCSYM: /* BSS " */
+ case N_ROSYM: /* Read-only data seg var -- static. */
+ case N_NBSTS: /* Gould nobase. */
+ case N_NBLCS: /* symbols. */
+ case N_FUN:
+ case N_GSYM: /* Global (extern) variable; can be
+ data or bss (sigh FIXME). */
+
+ /* 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 'S':
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ ADD_PSYMBOL_ADDR_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ objfile->static_psymbols,
+ CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+ case 'G':
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ /* The addresses in these entries are reported to be
+ wrong. See the code that reads 'G's for symtabs. */
+ ADD_PSYMBOL_ADDR_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ objfile->global_psymbols,
+ CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+
+ case 'T':
+ if (p != namestring) /* a name is there, not just :T... */
+ {
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ objfile->static_psymbols,
+ CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ if (p[2] == 't')
+ {
+ /* Also a typedef with the same name. */
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, psymtab_language,
+ objfile);
+ p += 1;
+ }
+ }
+ goto check_enum;
+ case 't':
+ if (p != namestring) /* a name is there, not just :T... */
+ {
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ objfile->static_psymbols,
+ CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ }
+ 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 the
+ enum in a nameless type. GCC2 does this. */
+
+ /* 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. Also, numbers can come
+ in pairs like (0,26). Skip over it. */
+ while ((*p >= '0' && *p <= '9')
+ || *p == '(' || *p == ',' || *p == ')'
+ || *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,
+ objfile->static_psymbols, 0,
+ psymtab_language, objfile);
+ /* 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,
+ objfile->static_psymbols, CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+
+ case 'f':
+#ifdef DBXREAD_ONLY
+ /* Kludges for ELF/STABS with Sun ACC */
+ last_function_name = namestring;
+ if (pst && pst->textlow == 0)
+ pst->textlow = CUR_SYMBOL_VALUE;
+#if 0
+ if (startup_file_end == 0)
+ startup_file_end = CUR_SYMBOL_VALUE;
+#endif
+ /* End kludge. */
+#endif /* DBXREAD_ONLY */
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ objfile->static_psymbols, CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+
+ /* Global functions were ignored here, but now they
+ are put into the global psymtab like one would expect.
+ They're also in the minimal symbol table. */
+ case 'F':
+#ifdef DBXREAD_ONLY
+ /* Kludges for ELF/STABS with Sun ACC */
+ last_function_name = namestring;
+ if (pst && pst->textlow == 0)
+ pst->textlow = CUR_SYMBOL_VALUE;
+#if 0
+ if (startup_file_end == 0)
+ startup_file_end = CUR_SYMBOL_VALUE;
+#endif
+ /* End kludge. */
+#endif /* DBXREAD_ONLY */
+ ADD_PSYMBOL_TO_LIST (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ objfile->global_psymbols, CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ 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':
+ 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 ':'. */
+ complain (&unknown_symchar_complaint, p[1]);
+ continue;
+ }
+
+ case N_EXCL:
+#ifdef DBXREAD_ONLY
+
+ 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, CUR_SYMBOL_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 *));
+ memcpy ((PTR)dependency_list, (PTR)orig,
+ (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);
+ }
+#endif /* DBXREAD_ONLY */
+ continue;
+
+ case N_RBRAC:
+#ifdef HANDLE_RBRAC
+ HANDLE_RBRAC(CUR_SYMBOL_VALUE);
+ continue;
+#endif
+ 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_NSYMS: /* Ultrix 4.0: symbol count */
+ case N_DEFD: /* GNU Modula-2 */
+
+ case N_OBJ: /* useless types from Solaris */
+ case N_OPT:
+ case N_ENDM:
+ /* 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,
+ local_hex_string ((unsigned long) CUR_SYMBOL_TYPE));
+ continue;
+ }
diff --git a/gnu/usr.bin/gdb/printcmd.c b/gnu/usr.bin/gdb/gdb/printcmd.c
index 6edd7bd2c2f3..3530ac2f32f0 100644
--- a/gnu/usr.bin/gdb/printcmd.c
+++ b/gnu/usr.bin/gdb/gdb/printcmd.c
@@ -1,41 +1,39 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)printcmd.c 6.5 (Berkeley) 5/8/91";
-#endif /* not lint */
-
/* Print values for GNU debugger GDB.
- Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 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
+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.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include <stdio.h>
#include "defs.h"
-#include "param.h"
+#include <string.h>
+#include <varargs.h>
#include "frame.h"
#include "symtab.h"
+#include "gdbtypes.h"
#include "value.h"
+#include "language.h"
#include "expression.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "breakpoint.h"
+#include "demangle.h"
+
+extern int asm_demangle; /* Whether to demangle syms in asm printouts */
+extern int addressprint; /* Whether to print hex addresses in HLL " */
struct format_data
{
@@ -65,19 +63,122 @@ static CORE_ADDR last_examine_address;
static value last_examine_value;
+/* Largest offset between a symbolic value and an address, that will be
+ printed as `0x1234 <symbol+offset>'. */
+
+static unsigned int max_symbolic_offset = UINT_MAX;
+
+/* Append the source filename and linenumber of the symbol when
+ printing a symbolic value as `<symbol at filename:linenum>' if set. */
+static int print_symbol_filename = 0;
+
/* Number of auto-display expression currently being displayed.
- So that we can deleted it if we get an error or a signal within it.
+ So that we can disable it if we get an error or a signal within it.
-1 when not doing one. */
int current_display_number;
-static void do_one_display ();
+/* 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;
-void do_displays ();
-void print_address ();
-void print_floating ();
-void print_scalar_formatted ();
-void print_formatted_address ();
+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 enable status;
+};
+
+/* Chain of expressions whose values should be displayed
+ automatically each time the program stops. */
+
+static struct display *display_chain;
+
+static int display_number;
+
+/* Prototypes for local functions */
+
+static void
+delete_display PARAMS ((int));
+
+static void
+enable_display PARAMS ((char *, int));
+
+static void
+disable_display_command PARAMS ((char *, int));
+
+static void
+disassemble_command PARAMS ((char *, int));
+
+static void
+printf_command PARAMS ((char *, int));
+
+static void
+print_frame_nameless_args PARAMS ((struct frame_info *, long, int, int,
+ FILE *));
+
+static void
+display_info PARAMS ((char *, int));
+
+static void
+do_one_display PARAMS ((struct display *));
+
+static void
+undisplay_command PARAMS ((char *, int));
+
+static void
+free_display PARAMS ((struct display *));
+
+static void
+display_command PARAMS ((char *, int));
+
+static void
+x_command PARAMS ((char *, int));
+
+static void
+address_info PARAMS ((char *, int));
+
+static void
+set_command PARAMS ((char *, int));
+
+static void
+output_command PARAMS ((char *, int));
+
+static void
+call_command PARAMS ((char *, int));
+
+static void
+inspect_command PARAMS ((char *, int));
+
+static void
+print_command PARAMS ((char *, int));
+
+static void
+print_command_1 PARAMS ((char *, int, int));
+
+static void
+validate_format PARAMS ((struct format_data, char *));
+
+static void
+do_examine PARAMS ((struct format_data, CORE_ADDR));
+
+static void
+print_formatted PARAMS ((value, int, int));
+
+static struct format_data
+decode_format PARAMS ((char **, int, int));
/* Decode a format specification. *STRING_PTR should point to it.
@@ -90,11 +191,11 @@ void print_formatted_address ();
found in the specification. In addition, *STRING_PTR is advanced
past the specification and past all whitespace following it. */
-struct format_data
+static struct format_data
decode_format (string_ptr, oformat, osize)
char **string_ptr;
- char oformat;
- char osize;
+ int oformat;
+ int osize;
{
struct format_data val;
register char *p = *string_ptr;
@@ -113,20 +214,13 @@ decode_format (string_ptr, oformat, osize)
{
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') || (*p >= 'A' && *p <= 'Z'))
+ else if (*p >= 'a' && *p <= 'z')
val.format = *p++;
else
break;
}
-#ifndef LONG_LONG
+#ifndef CC_HAS_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')
@@ -155,7 +249,6 @@ decode_format (string_ptr, oformat, osize)
{
case 'a':
case 's':
- case 'A':
/* Addresses must be words. */
val.size = osize ? 'w' : osize;
break;
@@ -189,8 +282,8 @@ decode_format (string_ptr, oformat, osize)
static void
print_formatted (val, format, size)
register value val;
- register char format;
- char size;
+ register int format;
+ int size;
{
int len = TYPE_LENGTH (VALUE_TYPE (val));
@@ -201,10 +294,16 @@ print_formatted (val, format, size)
{
case 's':
next_address = VALUE_ADDRESS (val)
- + value_print (value_addr (val), stdout, 0, Val_pretty_default);
+ + value_print (value_addr (val), stdout, format, Val_pretty_default);
break;
case 'i':
+ /* The old comment says
+ "Force output out, print_insn not using _filtered".
+ I'm not completely sure what that means, I suspect most print_insn
+ now do use _filtered, so I guess it's obsolete. */
+ /* We often wrap here if there are long symbolic names. */
+ wrap_here (" ");
next_address = VALUE_ADDRESS (val)
+ print_insn (VALUE_ADDRESS (val), stdout);
break;
@@ -212,6 +311,7 @@ print_formatted (val, format, size)
default:
if (format == 0
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ARRAY
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRING
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION
|| VALUE_REPEATED (val))
@@ -233,139 +333,86 @@ void
print_scalar_formatted (valaddr, type, format, size, stream)
char *valaddr;
struct type *type;
- char format;
+ int format;
int size;
FILE *stream;
{
LONGEST val_long;
int len = TYPE_LENGTH (type);
- if (size == 'g' && sizeof (LONGEST) < 8
- && format == 'x')
+ if (len > sizeof (LONGEST)
+ && (format == 't'
+ || format == 'c'
+ || format == 'o'
+ || format == 'u'
+ || format == 'd'
+ || format == 'x'))
{
- /* ok, we're going to have to get fancy here. Assumption: a
- long is four bytes. */
- unsigned long v1, v2, tmp;
-
- v1 = unpack_long (builtin_type_long, valaddr);
- v2 = unpack_long (builtin_type_long, valaddr + 4);
-
-#ifdef BYTES_BIG_ENDIAN
-#else
- /* 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);
- }
+ /* We can't print it normally, but we can print it in hex.
+ Printing it in the wrong radix is more useful than saying
+ "use /x, you dummy". */
+ /* FIXME: we could also do octal or binary if that was the
+ desired format. */
+ /* FIXME: we should be using the size field to give us a minimum
+ field width to print. */
+ val_print_type_code_int (type, valaddr, stream);
return;
}
-
+
val_long = unpack_long (type, valaddr);
- /* If value is unsigned, truncate it in case negative. */
+ /* If we are printing it as unsigned, truncate it in case it is actually
+ a negative signed value (e.g. "print/u (short)-1" should print 65535
+ (if shorts are 16 bits) instead of 4294967295). */
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;
+ if (len < sizeof (LONGEST))
+ val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1;
}
switch (format)
{
case 'x':
-#ifdef LONG_LONG
if (!size)
- size = (len < sizeof (long long) ? 'w' : 'g');
- switch (size)
- {
- case 'b':
- fprintf_filtered (stream, "0x%02llx", val_long);
- break;
- case 'h':
- fprintf_filtered (stream, "0x%04llx", val_long);
- break;
- case 0: /* no size specified, like in print */
- 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
- switch (size)
{
- case 'b':
- fprintf_filtered (stream, "0x%02x", val_long);
- break;
- case 'h':
- fprintf_filtered (stream, "0x%04x", val_long);
- break;
- case 0: /* no size specified, like in print */
- case 'w':
- fprintf_filtered (stream, "0x%08x", val_long);
- break;
- case 'g':
- fprintf_filtered (stream, "0x%o16x", val_long);
- break;
- default:
- error ("Undefined output size \"%c\".", size);
+ /* no size specified, like in print. Print varying # of digits. */
+ print_longest (stream, 'x', 1, val_long);
}
-#endif /* not LONG_LONG */
+ else
+ switch (size)
+ {
+ case 'b':
+ case 'h':
+ case 'w':
+ case 'g':
+ print_longest (stream, size, 1, val_long);
+ break;
+ default:
+ error ("Undefined output size \"%c\".", size);
+ }
break;
case 'd':
-#ifdef LONG_LONG
- fprintf_filtered (stream, "%lld", val_long);
-#else
- fprintf_filtered (stream, "%d", val_long);
-#endif
+ print_longest (stream, 'd', 1, val_long);
break;
case 'u':
-#ifdef LONG_LONG
- fprintf_filtered (stream, "%llu", val_long);
-#else
- fprintf_filtered (stream, "%u", val_long);
-#endif
+ print_longest (stream, 'u', 0, val_long);
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
+ print_longest (stream, 'o', 1, val_long);
else
fprintf_filtered (stream, "0");
break;
case 'a':
- print_address ((CORE_ADDR) val_long, stream);
- break;
-
- case 'A':
- print_formatted_address ((CORE_ADDR) val_long, stream);
+ print_address (unpack_pointer (type, valaddr), stream);
break;
case 'c':
- value_print (value_from_long (builtin_type_char, val_long), stream, 0,
+ value_print (value_from_longest (builtin_type_char, val_long), stream, 0,
Val_pretty_default);
break;
@@ -374,68 +421,62 @@ print_scalar_formatted (valaddr, type, format, size, stream)
type = builtin_type_float;
else if (len == sizeof (double))
type = builtin_type_double;
- print_floating(valaddr, type, stream);
+ print_floating (valaddr, type, stream);
break;
case 0:
abort ();
- default:
- error ("Undefined output format \"%c\".", format);
- }
-}
-
-/* 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;
- int len = TYPE_LENGTH (type);
-
- doub = unpack_double (type, valaddr, &inv);
- if (inv)
- fprintf_filtered (stream, "Invalid float value");
- else if (doub != doub)
- {
- /* Surely it is an IEEE floating point NaN. */
+ case 't':
+ /* Binary; 't' stands for "two". */
+ {
+ char bits[8*(sizeof val_long) + 1];
+ char *cp = bits;
+ int width;
+
+ if (!size)
+ width = 8*(sizeof val_long);
+ else
+ switch (size)
+ {
+ case 'b':
+ width = 8;
+ break;
+ case 'h':
+ width = 16;
+ break;
+ case 'w':
+ width = 32;
+ break;
+ case 'g':
+ width = 64;
+ break;
+ default:
+ error ("Undefined output size \"%c\".", size);
+ }
- long low, high, *arg = (long *)valaddr; /* ASSUMED 32 BITS */
- int nonneg;
+ bits[width] = '\0';
+ while (width-- > 0)
+ {
+ bits[width] = (val_long & 1) ? '1' : '0';
+ val_long >>= 1;
+ }
+ if (!size)
+ {
+ while (*cp && *cp == '0')
+ cp++;
+ if (*cp == '\0')
+ cp--;
+ }
+ fprintf_filtered (stream, local_binary_format_prefix());
+ fprintf_filtered (stream, cp);
+ fprintf_filtered (stream, local_binary_format_suffix());
+ }
+ break;
- if (len <= sizeof(float))
- {
- /* It's single precision. */
- low = *arg;
- nonneg = low >= 0;
- low &= 0x7fffff;
- high = 0;
- }
- else
- {
- /* It's double precision.
- Get the high and low words of the fraction.
- Distinguish big and little-endian machines. */
-#ifdef WORDS_BIG_ENDIAN
- low = arg[1], high = arg[0];
-#else
- low = arg[0], high = arg[1];
-#endif
- nonneg = high >= 0;
- high &= 0xfffff;
- }
- if (high)
- fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + nonneg, high, low);
- else
- fprintf_filtered (stream, "-NaN(0x%lx)" + nonneg, low);
+ default:
+ error ("Undefined output format \"%c\".", format);
}
- else
- fprintf_filtered (stream, len <= sizeof(float) ? "%.6g" : "%.17g", doub);
}
/* Specify default address for `x' command.
@@ -449,31 +490,83 @@ set_next_address (addr)
/* Make address available to the user as $_. */
set_internalvar (lookup_internalvar ("_"),
- value_from_long (builtin_type_int, (LONGEST) addr));
+ value_from_longest (lookup_pointer_type (builtin_type_void),
+ (LONGEST) addr));
}
-/* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> on STREAM. */
+/* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> on STREAM,
+ after LEADIN. Print nothing if no symbolic name is found nearby.
+ 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. However note that DO_DEMANGLE can be overridden by the specific
+ settings of the demangle and asm_demangle variables. */
void
-print_address_symbolic (addr, stream)
+print_address_symbolic (addr, stream, do_demangle, leadin)
CORE_ADDR addr;
FILE *stream;
+ int do_demangle;
+ char *leadin;
{
- register char *format;
- int name_location;
- register int i = find_pc_misc_function (addr);
-
- /* If nothing comes out, don't print anything symbolic. */
- if (i < 0) return;
- name_location = misc_function_vector[i].address;
+ CORE_ADDR name_location;
+ register struct symbol *symbol;
+ char *name;
- if (addr - name_location)
- format = " <%s+%d>";
+ /* First try to find the address in the symbol tables to find
+ static functions. If that doesn't succeed we try the minimal symbol
+ vector for symbols in non-text space.
+ FIXME: Should find a way to get at the static non-text symbols too. */
+
+ symbol = find_pc_function (addr);
+ if (symbol)
+ {
+ name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
+ if (do_demangle)
+ name = SYMBOL_SOURCE_NAME (symbol);
+ else
+ name = SYMBOL_LINKAGE_NAME (symbol);
+ }
else
- format = " <%s>";
+ {
+ register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (addr);
- fprintf_filtered (stream, format,
- misc_function_vector[i].name, addr - name_location);
+ /* If nothing comes out, don't print anything symbolic. */
+ if (msymbol == NULL)
+ return;
+ name_location = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (do_demangle)
+ name = SYMBOL_SOURCE_NAME (msymbol);
+ else
+ name = SYMBOL_LINKAGE_NAME (msymbol);
+ }
+
+ /* If the nearest symbol is too far away, don't print anything symbolic. */
+
+ /* For when CORE_ADDR is larger than unsigned int, we do math in
+ CORE_ADDR. But when we detect unsigned wraparound in the
+ CORE_ADDR math, we ignore this test and print the offset,
+ because addr+max_symbolic_offset has wrapped through the end
+ of the address space back to the beginning, giving bogus comparison. */
+ if (addr > name_location + max_symbolic_offset
+ && name_location + max_symbolic_offset > name_location)
+ return;
+
+ fputs_filtered (leadin, stream);
+ fputs_filtered ("<", stream);
+ fputs_filtered (name, stream);
+ if (addr != name_location)
+ fprintf_filtered (stream, "+%u", (unsigned int)(addr - name_location));
+
+ /* Append source filename and line number if desired. */
+ if (symbol && print_symbol_filename)
+ {
+ struct symtab_and_line sal;
+
+ sal = find_pc_line (addr, 0);
+ if (sal.symtab)
+ fprintf_filtered (stream, " at %s:%d", sal.symtab->filename, sal.line);
+ }
+ fputs_filtered (">", stream);
}
/* Print address ADDR symbolically on STREAM.
@@ -485,35 +578,47 @@ print_address (addr, stream)
CORE_ADDR addr;
FILE *stream;
{
- fprintf_filtered (stream, "0x%x", addr);
- print_address_symbolic (addr, stream);
+#if 0 && defined (ADDR_BITS_REMOVE)
+ /* This is wrong for pointer to char, in which we do want to print
+ the low bits. */
+ fprintf_filtered (stream, local_hex_format(),
+ (unsigned long) ADDR_BITS_REMOVE(addr));
+#else
+ fprintf_filtered (stream, local_hex_format(), (unsigned long) addr);
+#endif
+ print_address_symbolic (addr, stream, asm_demangle, " ");
}
-/* Like print_address but opnly prints symbolically. */
+/* Print address ADDR symbolically on STREAM. Parameter DEMANGLE
+ controls whether to print the symbolic name "raw" or demangled.
+ Global setting "addressprint" controls whether to print hex address
+ or not. */
void
-print_formatted_address (addr, stream)
+print_address_demangle (addr, stream, do_demangle)
CORE_ADDR addr;
FILE *stream;
+ int do_demangle;
{
- register int i = 0;
- register char *format;
- register struct symbol *fs;
- char *name;
- int name_location;
-
- i = find_pc_partial_function (addr, &name, &name_location);
-
- /* If nothing comes out, don't print anything symbolic. */
-
- if (i == 0)
- fprintf_filtered (stream, "0x%x", addr);
- else if (addr - name_location)
- fprintf_filtered (stream, "%s+%d", name, addr - name_location);
- else
- fprintf_filtered (stream, "%s", name);
+ if (addr == 0) {
+ fprintf_filtered (stream, "0");
+ } else if (addressprint) {
+ fprintf_filtered (stream, local_hex_format(), (unsigned long) addr);
+ print_address_symbolic (addr, stream, do_demangle, " ");
+ } else {
+ print_address_symbolic (addr, stream, do_demangle, "");
+ }
}
+
+/* These are the types that $__ will get after an examine command of one
+ of these sizes. */
+
+static struct type *examine_b_type;
+static struct type *examine_h_type;
+static struct type *examine_w_type;
+static struct type *examine_g_type;
+
/* Examine data at address ADDR in format FMT.
Fetch it from memory and print on stdout. */
@@ -525,7 +630,7 @@ do_examine (fmt, addr)
register char format = 0;
register char size;
register int count = 1;
- struct type *val_type;
+ struct type *val_type = NULL;
register int i;
register int maxelts;
@@ -540,17 +645,13 @@ do_examine (fmt, addr)
size = 'b';
if (size == 'b')
- val_type = builtin_type_char;
+ val_type = examine_b_type;
else if (size == 'h')
- val_type = builtin_type_short;
+ val_type = examine_h_type;
else if (size == 'w')
- val_type = builtin_type_long;
+ val_type = examine_w_type;
else if (size == 'g')
-#ifndef LONG_LONG
- val_type = builtin_type_double;
-#else
- val_type = builtin_type_long_long;
-#endif
+ val_type = examine_g_type;
maxelts = 8;
if (size == 'w')
@@ -598,18 +699,27 @@ validate_format (fmt, cmdname)
fmt.format, cmdname);
}
+/* Evaluate string EXP as an expression in the current language and
+ print the resulting value. EXP may contain a format specifier as the
+ first argument ("/x myvar" for example, to print myvar in hex).
+ */
+
static void
-print_command (exp)
+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 histindex;
int cleanup = 0;
+ /* Pass inspect flag to the rest of the print routines in a global (sigh). */
+ inspect_it = inspect;
+
if (exp && *exp == '/')
{
exp++;
@@ -617,30 +727,101 @@ print_command (exp)
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);
+ extern int objectprint;
+ struct type *type;
+ expr = parse_expression (exp);
old_chain = make_cleanup (free_current_contents, &expr);
cleanup = 1;
val = evaluate_expression (expr);
+
+ /* C++: figure out what type we actually want to print it as. */
+ type = VALUE_TYPE (val);
+
+ if (objectprint
+ && ( TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF)
+ && ( TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_UNION))
+ {
+ value v;
+
+ v = value_from_vtable_info (val, TYPE_TARGET_TYPE (type));
+ if (v != 0)
+ {
+ val = v;
+ type = VALUE_TYPE (val);
+ }
+ }
}
else
val = access_value_history (0);
- histindex = record_latest_value (val);
- if (histindex >= 0) printf_filtered ("$%d = ", histindex);
+ if (voidprint || (val && VALUE_TYPE (val) &&
+ TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_VOID))
+ {
+ int histindex = record_latest_value (val);
- print_formatted (val, format, fmt.size);
- printf_filtered ("\n");
+ 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 */
+}
+
+/* ARGSUSED */
+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 */
+/* ARGSUSED */
+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. */
+/* ARGSUSED */
+static void
+call_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ print_command_1 (exp, 0, 0);
}
+/* ARGSUSED */
static void
-output_command (exp)
+output_command (exp, from_tty)
char *exp;
+ int from_tty;
{
struct expression *expr;
register struct cleanup *old_chain;
@@ -652,11 +833,11 @@ output_command (exp)
{
exp++;
fmt = decode_format (&exp, 0, 0);
- validate_format (fmt, "print");
+ validate_format (fmt, "output");
format = fmt.format;
}
- expr = parse_c_expression (exp);
+ expr = parse_expression (exp);
old_chain = make_cleanup (free_current_contents, &expr);
val = evaluate_expression (expr);
@@ -666,23 +847,29 @@ output_command (exp)
do_cleanups (old_chain);
}
+/* ARGSUSED */
static void
-set_command (exp)
+set_command (exp, from_tty)
char *exp;
+ int from_tty;
{
- struct expression *expr = parse_c_expression (exp);
+ struct expression *expr = parse_expression (exp);
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
evaluate_expression (expr);
do_cleanups (old_chain);
}
+/* ARGSUSED */
static void
-address_info (exp)
+address_info (exp, from_tty)
char *exp;
+ int from_tty;
{
register struct symbol *sym;
- register CORE_ADDR val;
+ register struct minimal_symbol *msymbol;
+ register long val;
+ register long basereg;
int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero
if exp is a field of `this'. */
@@ -690,24 +877,21 @@ address_info (exp)
error ("Argument required.");
sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE,
- &is_a_field_of_this);
- if (sym == 0)
+ &is_a_field_of_this, (struct symtab **)NULL);
+ if (sym == NULL)
{
- 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;
+ msymbol = lookup_minimal_symbol (exp, (struct objfile *) NULL);
- 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);
+ if (msymbol != NULL)
+ printf ("Symbol \"%s\" is at %s in a file compiled without debugging.\n",
+ exp,
+ local_hex_string((unsigned long) SYMBOL_VALUE_ADDRESS (msymbol)));
else
error ("No symbol \"%s\" in current context.", exp);
return;
@@ -715,6 +899,7 @@ address_info (exp)
printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym));
val = SYMBOL_VALUE (sym);
+ basereg = SYMBOL_BASEREG (sym);
switch (SYMBOL_CLASS (sym))
{
@@ -724,7 +909,8 @@ address_info (exp)
break;
case LOC_LABEL:
- printf ("a label at address 0x%x", val);
+ printf ("a label at address %s",
+ local_hex_string((unsigned long) SYMBOL_VALUE_ADDRESS (sym)));
break;
case LOC_REGISTER:
@@ -732,23 +918,42 @@ address_info (exp)
break;
case LOC_STATIC:
- printf ("static at address 0x%x", val);
+ printf ("static storage at address %s",
+ local_hex_string((unsigned long) SYMBOL_VALUE_ADDRESS (sym)));
break;
case LOC_REGPARM:
printf ("an argument in register %s", reg_names[val]);
break;
-
+
+ case LOC_REGPARM_ADDR:
+ printf ("address of an argument in register %s", reg_names[val]);
+ break;
+
case LOC_ARG:
- printf ("an argument at offset %d", val);
+ printf ("an argument at offset %ld", val);
+ break;
+
+ case LOC_LOCAL_ARG:
+ printf ("an argument at frame offset %ld", val);
break;
case LOC_LOCAL:
- printf ("a local variable at frame offset %d", val);
+ printf ("a local variable at frame offset %ld", val);
break;
case LOC_REF_ARG:
- printf ("a reference argument at offset %d", val);
+ printf ("a reference argument at offset %ld", val);
+ break;
+
+ case LOC_BASEREG:
+ printf ("a variable at offset %ld from register %s",
+ val, reg_names[basereg]);
+ break;
+
+ case LOC_BASEREG_ARG:
+ printf ("an argument at offset %ld from register %s",
+ val, reg_names[basereg]);
break;
case LOC_TYPEDEF:
@@ -756,8 +961,16 @@ address_info (exp)
break;
case LOC_BLOCK:
- printf ("a function at address 0x%x",
- BLOCK_START (SYMBOL_BLOCK_VALUE (sym)));
+ printf ("a function at address %s",
+ local_hex_string((unsigned long) BLOCK_START (SYMBOL_BLOCK_VALUE (sym))));
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ printf_filtered ("optimized out");
+ break;
+
+ default:
+ printf ("of unknown (botched) type");
break;
}
printf (".\n");
@@ -781,15 +994,13 @@ x_command (exp, from_tty)
{
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);
+ expr = parse_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. */
@@ -797,6 +1008,8 @@ x_command (exp, from_tty)
*exp = 0;
old_chain = make_cleanup (free_current_contents, &expr);
val = evaluate_expression (expr);
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF)
+ val = value_ind (val);
/* In rvalue contexts, such as this, functions are coerced into
pointers to functions. This makes "x/i main" work. */
if (/* last_format == 'i'
@@ -804,137 +1017,32 @@ x_command (exp, from_tty)
&& VALUE_LVAL (val) == lval_memory)
next_address = VALUE_ADDRESS (val);
else
- next_address = (CORE_ADDR) value_as_long (val);
+ next_address = value_as_pointer (val);
do_cleanups (old_chain);
}
do_examine (fmt, next_address);
+ /* If the examine succeeds, we remember its size and format for next time. */
+ last_size = fmt.size;
+ last_format = fmt.format;
+
/* Set a couple of internal variables if appropriate. */
if (last_examine_value)
{
- /* Make last address examined available to the user as $_. */
+ /* Make last address examined available to the user as $_. Use
+ the correct pointer type. */
set_internalvar (lookup_internalvar ("_"),
- value_from_long (builtin_type_int,
- (LONGEST) last_examine_address));
+ value_from_longest (
+ lookup_pointer_type (VALUE_TYPE (last_examine_value)),
+ (LONGEST) last_examine_address));
/* Make contents of last address examined available to the user as $__.*/
set_internalvar (lookup_internalvar ("__"), last_examine_value);
}
}
-
-/* Commands for printing types of things. */
-
-static void
-whatis_command (exp)
- char *exp;
-{
- 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 = ");
- /* 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. */
- type_print (VALUE_TYPE (val), "", stdout, -1);
- printf_filtered ("\n");
-
- if (exp)
- do_cleanups (old_chain);
-}
-static void
-ptype_command (typename)
- char *typename;
-{
- register char *p = typename;
- register int len;
- extern struct block *get_current_block ();
- register struct block *b
- = (have_inferior_p () || have_core_file_p ()) ? get_current_block () : 0;
- register struct type *type;
-
- if (typename == 0)
- error_no_arg ("type name");
-
- 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);
- if (sym == 0)
- error ("No type named %s.", typename);
- 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");
- }
- printf_filtered (" %s. Type \"help ptype\".\n", typename);
- type = SYMBOL_TYPE (sym);
- }
- }
-
- type_print (type, "", stdout, 1);
- printf_filtered ("\n");
-}
-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. */
@@ -946,7 +1054,6 @@ display_command (exp, from_tty)
struct format_data fmt;
register struct expression *expr;
register struct display *new;
- extern struct block *innermost_block;
if (exp == 0)
{
@@ -971,7 +1078,7 @@ display_command (exp, from_tty)
}
innermost_block = 0;
- expr = parse_c_expression (exp);
+ expr = parse_expression (exp);
new = (struct display *) xmalloc (sizeof (struct display));
@@ -983,7 +1090,7 @@ display_command (exp, from_tty)
new->status = enabled;
display_chain = new;
- if (from_tty && have_inferior_p ())
+ if (from_tty && target_has_execution)
do_one_display (new);
dont_repeat ();
@@ -993,8 +1100,8 @@ static void
free_display (d)
struct display *d;
{
- free (d->exp);
- free (d);
+ free ((PTR)d->exp);
+ free ((PTR)d);
}
/* Clear out the display_chain.
@@ -1006,17 +1113,17 @@ clear_displays ()
{
register struct display *d;
- while (d = display_chain)
+ while ((d = display_chain) != NULL)
{
- free (d->exp);
+ free ((PTR)d->exp);
display_chain = d->next;
- free (d);
+ free ((PTR)d);
}
}
/* Delete the auto-display number NUM. */
-void
+static void
delete_display (num)
int num;
{
@@ -1050,13 +1157,13 @@ delete_display (num)
Specify the element numbers. */
static void
-undisplay_command (args)
+undisplay_command (args, from_tty)
char *args;
+ int from_tty;
{
register char *p = args;
register char *p1;
register int num;
- register struct display *d, *d1;
if (args == 0)
{
@@ -1108,6 +1215,8 @@ do_one_display (d)
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);
@@ -1120,9 +1229,12 @@ do_one_display (d)
printf_filtered ("\n");
else
printf_filtered (" ");
- do_examine (d->format,
- (CORE_ADDR) value_as_long (evaluate_expression (d->exp)));
-
+
+ addr = value_as_pointer (evaluate_expression (d->exp));
+ if (d->format.format == 'i')
+ addr = ADDR_BITS_REMOVE (addr);
+
+ do_examine (d->format, addr);
}
else
{
@@ -1182,7 +1294,9 @@ disable_current_display ()
}
static void
-display_info ()
+display_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
{
register struct display *d;
@@ -1208,9 +1322,10 @@ Num Enb Expression\n");
}
}
-void
-enable_display (args)
+static void
+enable_display (args, from_tty)
char *args;
+ int from_tty;
{
register char *p = args;
register char *p1;
@@ -1247,14 +1362,14 @@ enable_display (args)
}
}
-void
+/* ARGSUSED */
+static void
disable_display_command (args, from_tty)
char *args;
int from_tty;
{
register char *p = args;
register char *p1;
- register int num;
register struct display *d;
if (p == 0)
@@ -1271,8 +1386,6 @@ disable_display_command (args, from_tty)
if (*p1 && *p1 != ' ' && *p1 != '\t')
error ("Arguments must be display numbers.");
- num = atoi (p);
-
disable_display (atoi (p));
p = p1;
@@ -1295,18 +1408,13 @@ print_variable_value (var, frame, stream)
value_print (val, stream, 0, Val_pretty_default);
}
-static int
-compare_ints (i, j)
- int *i, *j;
-{
- return *i - *j;
-}
-
/* 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). */
-static void print_frame_nameless_args ();
+/* 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)
@@ -1315,17 +1423,19 @@ print_frame_args (func, fi, num, stream)
int num;
FILE *stream;
{
- struct block *b;
+ struct block *b = NULL;
int nsyms = 0;
int first = 1;
register int i;
- register int last_regparm = 0;
- register struct symbol *lastsym, *sym, *nextsym;
+ register struct symbol *sym;
register value val;
- /* Offset of stack argument that is at the highest offset.
+ /* 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. */
- CORE_ADDR highest_offset = (CORE_ADDR) -1;
- register CORE_ADDR addr = FRAME_ARGS_ADDRESS (fi);
+ long highest_offset = -1;
+ int arg_size;
+ /* Number of ints of arguments that we have printed so far. */
+ int args_printed = 0;
if (func)
{
@@ -1338,72 +1448,83 @@ print_frame_args (func, fi, num, stream)
QUIT;
sym = BLOCK_SYM (b, i);
- if (SYMBOL_CLASS (sym) != LOC_REGPARM
- && SYMBOL_CLASS (sym) != LOC_ARG
- && SYMBOL_CLASS (sym) != LOC_REF_ARG)
- continue;
+ /* Keep track of the highest stack argument offset seen, and
+ skip over any kinds of symbols we don't care about. */
- /* Print the next arg. */
- if (SYMBOL_CLASS (sym) == LOC_REGPARM)
- val = value_from_register (SYMBOL_TYPE (sym),
- SYMBOL_VALUE (sym),
- FRAME_INFO_ID (fi));
- else
+ switch (SYMBOL_CLASS (sym)) {
+ case LOC_ARG:
+ case LOC_REF_ARG:
{
- int current_offset = SYMBOL_VALUE (sym);
- int arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym));
+ long current_offset = SYMBOL_VALUE (sym);
+
+ arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym));
- if (SYMBOL_CLASS (sym) == LOC_REF_ARG)
- val = value_at (SYMBOL_TYPE (sym),
- read_memory_integer (addr + current_offset,
- sizeof (CORE_ADDR)));
- else
- val = value_at (SYMBOL_TYPE (sym), addr + current_offset);
-
- /* Round up address of next arg to multiple of size of int. */
+ /* Compute address of next argument by adding the size of
+ this argument and rounding to an int boundary. */
current_offset
- = (((current_offset + sizeof (int) - 1) / sizeof (int))
- * sizeof (int));
+ = ((current_offset + arg_size + sizeof (int) - 1)
+ & ~(sizeof (int) - 1));
/* If this is the highest offset seen yet, set highest_offset. */
- if (highest_offset == (CORE_ADDR)-1
- || ((current_offset
- + (arg_size - sizeof (int) + 3) / (sizeof (int)))
- > 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);
}
+ /* We care about types of symbols, but don't need to keep track of
+ stack offsets in them. */
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG_ARG:
+ break;
+
+ /* Other types of symbols we just skip over. */
+ default:
+ continue;
+ }
+
+ /* We have to look up the symbol because arguments can have
+ two entries (one a parameter, one a local) and the one we
+ want is the local, which lookup_symbol will find for us.
+ This includes gcc1 (not gcc2) on the sparc when passing a
+ small structure and gcc2 when the argument type is float
+ and it is passed as a double and converted to float by
+ the prologue (in the latter case the type of the LOC_ARG
+ symbol is double and the type of the LOC_LOCAL symbol is
+ float). There are also LOC_ARG/LOC_REGISTER pairs which
+ are not combined in symbol-reading. */
+ /* But if the parameter name is null, don't try it.
+ Null parameter names occur on the RS/6000, for traceback tables.
+ FIXME, should we even print them? */
+
+ if (*SYMBOL_NAME (sym))
+ sym = lookup_symbol
+ (SYMBOL_NAME (sym),
+ b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+
+ /* Print the current arg. */
if (! first)
fprintf_filtered (stream, ", ");
- fputs_filtered (SYMBOL_NAME (sym), stream);
+ wrap_here (" ");
+ fprintf_symbol_filtered (stream, SYMBOL_SOURCE_NAME (sym),
+ SYMBOL_LANGUAGE (sym), DMGL_PARAMS | DMGL_ANSI);
fputs_filtered ("=", stream);
-/* Nonzero if a LOC_ARG which is a struct is useless. */
-#if !defined (STRUCT_ARG_SYM_GARBAGE)
-#define STRUCT_ARG_SYM_GARBAGE(gcc_p) 0
-#endif
-
- if (STRUCT_ARG_SYM_GARBAGE (b->gcc_compile_flag)
- && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
- && SYMBOL_CLASS (sym) == LOC_ARG)
- {
- /* Try looking up that name. SunOS4 puts out a usable
- symbol as a local variable (in addition to the one
- for the arg). */
- struct symbol *sym2 =
- lookup_symbol (SYMBOL_NAME (sym), b, VAR_NAMESPACE, 0);
-
- if (sym2 != NULL)
- val = value_of_variable (sym2);
- else
- {
- fputs_filtered ("?", stream);
- first = 0;
- continue;
- }
- }
-
- value_print (val, stream, 0, Val_no_prettyprint);
+ /* 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. We pass 2 as "recurse" to val_print because our
+ standard indentation here is 4 spaces, and val_print indents
+ 2 for each recurse. */
+ 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, 2, Val_no_prettyprint);
+ else
+ fputs_filtered ("???", stream);
first = 0;
}
@@ -1411,58 +1532,84 @@ print_frame_args (func, fi, num, stream)
enough about the stack to find them. */
if (num != -1)
{
- if (highest_offset != (CORE_ADDR) -1
- && num * sizeof (int) + FRAME_ARGS_SKIP > highest_offset)
- print_frame_nameless_args (fi, addr,
- highest_offset + sizeof (int),
- num * sizeof (int) + FRAME_ARGS_SKIP,
- stream);
- else
- print_frame_nameless_args (fi, addr, FRAME_ARGS_SKIP,
- num * sizeof (int) + FRAME_ARGS_SKIP,
- stream);
+ long start;
+
+ if (highest_offset == -1)
+ start = FRAME_ARGS_SKIP;
+ else
+ start = highest_offset;
+
+ print_frame_nameless_args (fi, start, num - args_printed,
+ first, stream);
}
}
+/* Print nameless args on STREAM.
+ FI is the frameinfo for this frame, 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 (fi, argsaddr, start, end, stream)
+print_frame_nameless_args (fi, start, num, first, stream)
struct frame_info *fi;
- CORE_ADDR argsaddr;
- int start;
- int end;
+ long start;
+ int num;
+ int first;
FILE *stream;
{
- extern void (*default_scalar_print)();
- LONGEST v;
- int p = start;
- char *s = "";
-
- for (p = start; p < end; p += sizeof(int)) {
- QUIT;
-#if defined(NAMELESS_ARG)
- v = NAMELESS_ARG(fi, (p - start) / sizeof(int));
+ int i;
+ CORE_ADDR argsaddr;
+ long arg_value;
+
+ for (i = 0; i < num; i++)
+ {
+ QUIT;
+#ifdef NAMELESS_ARG_VALUE
+ NAMELESS_ARG_VALUE (fi, start, &arg_value);
#else
- v = read_memory_integer (argsaddr + p, sizeof (int));
+ argsaddr = FRAME_ARGS_ADDRESS (fi);
+ if (!argsaddr)
+ return;
+
+ arg_value = read_memory_integer (argsaddr + start, sizeof (int));
#endif
- fprintf_filtered (stream, s);
- s = ", ";
- (*default_scalar_print) (stream, builtin_type_int, v);
- }
+
+ if (!first)
+ fprintf_filtered (stream, ", ");
+
+#ifdef PRINT_NAMELESS_INTEGER
+ PRINT_NAMELESS_INTEGER (stream, arg_value);
+#else
+#ifdef PRINT_TYPELESS_INTEGER
+ PRINT_TYPELESS_INTEGER (stream, builtin_type_int, (LONGEST) arg_value);
+#else
+ fprintf_filtered (stream, "%d", arg_value);
+#endif /* PRINT_TYPELESS_INTEGER */
+#endif /* PRINT_NAMELESS_INTEGER */
+ first = 0;
+ start += sizeof (int);
+ }
}
+/* ARGSUSED */
static void
-printf_command (arg)
+printf_command (arg, from_tty)
char *arg;
+ int from_tty;
{
register char *f;
register char *s = arg;
char *string;
value *val_args;
+ char *substrings;
+ char *current_substring;
int nargs = 0;
int allocated_args = 20;
- char *arg_bytes;
+ va_list args_to_vprintf;
+ struct cleanup *old_cleanups;
val_args = (value *) xmalloc (allocated_args * sizeof (value));
+ old_cleanups = make_cleanup (free_current_contents, &val_args);
if (s == 0)
error_no_arg ("format-control string and values to print");
@@ -1478,6 +1625,7 @@ printf_command (arg)
processing some kinds of escape sequence. */
f = string = (char *) alloca (strlen (s) + 1);
+
while (*s != '"')
{
int c = *s++;
@@ -1485,7 +1633,6 @@ printf_command (arg)
{
case '\0':
error ("Bad format string, non-terminated '\"'.");
- /* doesn't return */
case '\\':
switch (c = *s++)
@@ -1527,50 +1674,85 @@ printf_command (arg)
if (*s == ',') s++;
while (*s == ' ' || *s == '\t') s++;
+ /* Need extra space for the '\0's. Doubling the size is sufficient. */
+ substrings = alloca (strlen (string) * 2);
+ current_substring = substrings;
+
{
/* 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 {no_arg, int_arg, string_arg, double_arg, long_long_arg};
enum argclass *argclass;
+ enum argclass this_argclass;
+ char *last_arg;
int nargs_wanted;
- int argindex;
int lcount;
int i;
-
+
argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass);
nargs_wanted = 0;
f = string;
+ last_arg = string;
while (*f)
if (*f++ == '%')
{
lcount = 0;
- while (index ("0123456789.hlL-+ #", *f))
+ 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;
+ switch (*f)
+ {
+ case 's':
+ this_argclass = string_arg;
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ this_argclass = double_arg;
+ break;
+
+ case '*':
+ error ("`*' not supported for precision or width in printf");
+
+ case 'n':
+ error ("Format specifier `n' not supported in printf");
+
+ case '%':
+ this_argclass = no_arg;
+ break;
+
+ default:
+ if (lcount > 1)
+ this_argclass = long_long_arg;
+ else
+ this_argclass = int_arg;
+ break;
+ }
f++;
+ if (this_argclass != no_arg)
+ {
+ strncpy (current_substring, last_arg, f - last_arg);
+ current_substring += f - last_arg;
+ *current_substring++ = '\0';
+ last_arg = f;
+ argclass[nargs_wanted++] = this_argclass;
+ }
}
-
+
/* 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,
+ val_args = (value *) xrealloc ((char *) val_args,
(allocated_args *= 2)
* sizeof (value));
s1 = s;
@@ -1594,87 +1776,88 @@ printf_command (arg)
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;
+
+ /* FIXME: We should be using vprintf_filtered, but as long as it
+ has an arbitrary limit that is unacceptable. Correct fix is
+ for vprintf_filtered to scan down the format string so it knows
+ how big a buffer it needs (perhaps by putting a vasprintf (see
+ GNU C library) in libiberty).
+
+ But for now, just force out any pending output, so at least the output
+ appears in the correct order. */
+ wrap_here ((char *)NULL);
+
+ /* Now actually print them. */
+ current_substring = substrings;
for (i = 0; i < nargs; i++)
{
- if (argclass[i] == string_arg)
+ switch (argclass[i])
{
- 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)
+ case string_arg:
{
- *(long long *) &arg_bytes[argindex] = value_as_long (val_args[i]);
- argindex += sizeof (long long);
+ char *str;
+ CORE_ADDR tem;
+ int j;
+ tem = value_as_pointer (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;
+
+ /* Don't use printf_filtered because of arbitrary limit. */
+ printf (current_substring, str);
}
- else
+ break;
+ case double_arg:
+ {
+ double val = value_as_double (val_args[i]);
+ /* Don't use printf_filtered because of arbitrary limit. */
+ printf (current_substring, val);
+ break;
+ }
+ case long_long_arg:
+#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG)
+ {
+ long long val = value_as_long (val_args[i]);
+ /* Don't use printf_filtered because of arbitrary limit. */
+ printf (current_substring, val);
+ break;
+ }
+#else
+ error ("long long not supported in printf");
#endif
+ case int_arg:
{
- *((int *) &arg_bytes[argindex]) = value_as_long (val_args[i]);
- argindex += sizeof (int);
+ /* FIXME: there should be separate int_arg and long_arg. */
+ long val = value_as_long (val_args[i]);
+ /* Don't use printf_filtered because of arbitrary limit. */
+ printf (current_substring, val);
+ break;
}
+ default:
+ error ("internal error in printf_command");
+ }
+ /* Skip to the next substring. */
+ current_substring += strlen (current_substring) + 1;
}
+ /* Print the portion of the format string after the last argument. */
+ /* It would be OK to use printf_filtered here. */
+ printf (last_arg);
}
- vprintf (string, arg_bytes);
+ do_cleanups (old_cleanups);
}
-/* 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
@@ -1682,30 +1865,33 @@ containing_function_bounds (pc, low, high)
Two arguments are interpeted as bounds within which to dump
assembly. */
+/* ARGSUSED */
static void
disassemble_command (arg, from_tty)
char *arg;
int from_tty;
{
CORE_ADDR low, high;
+ char *name;
CORE_ADDR pc;
char *space_index;
+ name = NULL;
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");
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error ("No function contains program counter for selected frame.\n");
}
- else if (!(space_index = (char *) index (arg, ' ')))
+ 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");
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error ("No function contains specified address.\n");
}
else
{
@@ -1716,14 +1902,15 @@ disassemble_command (arg, from_tty)
}
printf_filtered ("Dump of assembler code ");
- if (!space_index)
+ if (name != NULL)
{
- 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);
+ {
+ printf_filtered ("from %s ", local_hex_string((unsigned long) low));
+ printf_filtered ("to %s:\n", local_hex_string((unsigned long) high));
+ }
/* Dump the specified range. */
for (pc = low; pc < high; )
@@ -1739,9 +1926,6 @@ disassemble_command (arg, from_tty)
}
-extern struct cmd_list_element *enablelist, *disablelist, *deletelist;
-extern struct cmd_list_element *cmdlist, *setlist;
-
void
_initialize_printcmd ()
{
@@ -1755,9 +1939,8 @@ _initialize_printcmd ()
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\
+ t(binary), 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\
@@ -1770,15 +1953,11 @@ 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.");
@@ -1825,19 +2004,29 @@ This is useful for formatted output in user-defined commands.");
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\
+"Evaluate expression EXP and assign result to variable VAR, using assignment\n\
+syntax appropriate for the current language (VAR = EXP or VAR := EXP for\n\
+example). VAR may be a debugger \"convenience\" variable (names starting\n\
+with $), a register (a few standard names starting with $), or an actual\n\
+variable in the program being debugged. EXP is any valid 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",
+\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 program.\n\
+The argument is the function name and arguments, in the notation of the\n\
+current working language. The result is printed and saved in the value\n\
+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\
+"Evaluate expression EXP and assign result to variable VAR, using assignment\n\
+syntax appropriate for the current language (VAR = EXP or VAR := EXP for\n\
+example). VAR may be a debugger \"convenience\" variable (names starting\n\
+with $), a register (a few standard names starting with $), or an actual\n\
+variable in the program being debugged. EXP is any valid expression.\n\
This may usually be abbreviated to simply \"set\".",
&setlist);
@@ -1854,7 +2043,7 @@ 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\
+{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\
@@ -1862,6 +2051,28 @@ 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)."));
+but no count or size letter (see \"x\" command).", NULL));
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.");
+
+ add_show_from_set (
+ add_set_cmd ("max-symbolic-offset", no_class, var_uinteger,
+ (char *)&max_symbolic_offset,
+ "Set the largest offset that will be printed in <symbol+1234> form.",
+ &setprintlist),
+ &showprintlist);
+ add_show_from_set (
+ add_set_cmd ("symbol-filename", no_class, var_boolean,
+ (char *)&print_symbol_filename,
+ "Set printing of source filename and line number with <symbol>.",
+ &setprintlist),
+ &showprintlist);
+
+ examine_b_type = init_type (TYPE_CODE_INT, 1, 0, NULL, NULL);
+ examine_h_type = init_type (TYPE_CODE_INT, 2, 0, NULL, NULL);
+ examine_w_type = init_type (TYPE_CODE_INT, 4, 0, NULL, NULL);
+ examine_g_type = init_type (TYPE_CODE_INT, 8, 0, NULL, NULL);
}
diff --git a/gnu/usr.bin/gdb/gdb/putenv.c b/gnu/usr.bin/gdb/gdb/putenv.c
new file mode 100644
index 000000000000..e2ea3572d91d
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/putenv.c
@@ -0,0 +1,111 @@
+/****************************************************************/
+/* */
+/* putenv(3) */
+/* */
+/* Change or add an environment entry */
+/* */
+/****************************************************************/
+/* origination 1987-Oct-7 T. Holm */
+/****************************************************************/
+
+/*
+Path: hoptoad!pacbell!ames!ll-xn!mit-eddie!uw-beaver!ssc-vax!uvicctr!tholm
+From: tholm@uvicctr.UUCP (Terrence W. Holm)
+Newsgroups: comp.os.minix
+Subject: putenv(3)
+Message-ID: <395@uvicctr.UUCP>
+Date: 5 May 88 06:40:52 GMT
+Organization: University of Victoria, Victoria B.C. Canada
+
+EFTH Minix report #2 - May 1988 - putenv(3)
+
+This is an implementation of putenv(3) that we
+wrote for Minix. Please consider this a public
+domain program.
+*/
+
+#include <stdio.h>
+
+#define PSIZE sizeof(char *)
+
+extern char **environ;
+
+char *strchr();
+char *malloc();
+
+/****************************************************************/
+/* */
+/* int */
+/* putenv( entry ) */
+/* */
+/* The "entry" should follow the form */
+/* "NAME=VALUE". This routine will search the */
+/* user environment for "NAME" and replace its */
+/* value with "VALUE". */
+/* */
+/* Note that "entry" is not copied, it is used */
+/* as the environment entry. This means that it */
+/* must not be unallocated or otherwise modifed */
+/* by the caller, unless it is replaced by a */
+/* subsequent putenv(). */
+/* */
+/* If the name is not found in the environment, */
+/* then a new vector of pointers is allocated, */
+/* "entry" is put at the end and the global */
+/* variable "environ" is updated. */
+/* */
+/* This function normally returns NULL, but -1 */
+/* is returned if it can not allocate enough */
+/* space using malloc(3), or "entry" does not */
+/* contain a '='. */
+/* */
+/****************************************************************/
+
+
+int
+putenv( entry )
+ char *entry;
+{
+ unsigned length;
+ unsigned size;
+ char *temp;
+ char **p;
+ char **new_environ;
+
+ /* Find the length of the "NAME=" */
+
+ temp = strchr(entry,'=');
+ if ( temp == 0 )
+ return( -1 );
+
+ length = (unsigned) (temp - entry + 1);
+
+
+ /* Scan through the environment looking for "NAME=" */
+
+ for ( p=environ; *p != 0 ; p++ )
+ if ( strncmp( entry, *p, length ) == 0 )
+ {
+ *p = entry;
+ return( 0 );
+ }
+
+
+ /* The name was not found, build a bigger environment */
+
+ size = p - environ;
+
+ new_environ = (char **) malloc( (size+2)*PSIZE );
+
+ if ( new_environ == (char **) NULL )
+ return( -1 );
+
+ memcpy ((char *) new_environ, (char *) environ, size*PSIZE );
+
+ new_environ[size] = entry;
+ new_environ[size+1] = NULL;
+
+ environ = new_environ;
+
+ return(0);
+}
diff --git a/gnu/usr.bin/gdb/regex.c b/gnu/usr.bin/gdb/gdb/regex.c
index 45c34780f6c2..75bf4e9fc234 100644
--- a/gnu/usr.bin/gdb/regex.c
+++ b/gnu/usr.bin/gdb/gdb/regex.c
@@ -1,25 +1,19 @@
/* 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 free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 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! */
+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. */
/* To test, compile with -Dtest.
This Dtestable feature turns this into a self-contained program
@@ -38,14 +32,6 @@
#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
@@ -82,7 +68,7 @@ init_syntax_once ()
if (done)
return;
- bzero (re_syntax_table, sizeof re_syntax_table);
+ memset (re_syntax_table, '\0', sizeof re_syntax_table);
for (c = 'a'; c <= 'z'; c++)
re_syntax_table[c] = Sword;
@@ -128,6 +114,7 @@ static int obscure_syntax = 0;
int
re_set_syntax (syntax)
+ int syntax;
{
int ret;
@@ -183,7 +170,7 @@ re_set_syntax (syntax)
pending_exact += c; \
}
-static int store_jump (), insert_jump ();
+static void store_jump (), insert_jump ();
char *
re_compile_pattern (pattern, size, bufp)
@@ -417,7 +404,7 @@ re_compile_pattern (pattern, size, bufp)
PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
/* Clear the whole map */
- bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+ memset (b, '\0', (1 << BYTEWIDTH) / BYTEWIDTH);
/* Read in characters and ranges, setting map bits */
while (1)
{
@@ -665,7 +652,7 @@ re_compile_pattern (pattern, size, bufp)
/* Store where `from' points a jump operation to jump to where `to' points.
`opcode' is the opcode to store. */
-static int
+static void
store_jump (from, opcode, to)
char *from, *to;
char opcode;
@@ -682,7 +669,7 @@ store_jump (from, opcode, to)
If you call this function, you must zero out pending_exact. */
-static int
+static void
insert_jump (op, from, to, current_end)
char op;
char *from, *to, *current_end;
@@ -712,13 +699,13 @@ re_compile_fastmap (bufp)
register char *fastmap = bufp->fastmap;
register unsigned char *p = pattern;
register unsigned char *pend = pattern + size;
- register int j, k;
+ register int j;
unsigned char *translate = (unsigned char *) bufp->translate;
unsigned char *stackb[NFAILURES];
unsigned char **stackp = stackb;
- bzero (fastmap, (1 << BYTEWIDTH));
+ memset (fastmap, '\0', (1 << BYTEWIDTH));
bufp->fastmap_accurate = 1;
bufp->can_be_null = 0;
@@ -1021,7 +1008,7 @@ re_match (pbufp, string, size, pos, regs)
int re_max_failures = 2000;
-static int bcmp_translate();
+static int memcmp_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.
@@ -1229,7 +1216,7 @@ re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
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))
+ if (translate ? memcmp_translate (d, d2, mcnt, translate) : memcmp (d, d2, mcnt))
goto fail;
d += mcnt, d2 += mcnt;
}
@@ -1306,7 +1293,7 @@ re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
return -2;
stackx = (unsigned char **) alloca (2 * (stacke - stackb)
* sizeof (char *));
- bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+ memcpy (stackx, stackb, (stacke - stackb) * sizeof (char *));
stackp = stackx + (stackp - stackb);
stacke = stackx + 2 * (stacke - stackb);
stackb = stackx;
@@ -1386,7 +1373,7 @@ re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
unsigned char **stackx
= (unsigned char **) alloca (2 * (stacke - stackb)
* sizeof (char *));
- bcopy (stackb, stackx, (stacke - stackb) * sizeof (char *));
+ memcpy (stackx, stackb, (stacke - stackb) * sizeof (char *));
stackp = stackx + (stackp - stackb);
stacke = stackx + 2 * (stacke - stackb);
stackb = stackx;
@@ -1547,7 +1534,7 @@ re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
}
static int
-bcmp_translate (s1, s2, len, translate)
+memcmp_translate (s1, s2, len, translate)
unsigned char *s1, *s2;
register int len;
unsigned char *translate;
diff --git a/gnu/usr.bin/gdb/regex.h b/gnu/usr.bin/gdb/gdb/regex.h
index d0d8a82835b6..6348c3eb6e45 100644
--- a/gnu/usr.bin/gdb/regex.h
+++ b/gnu/usr.bin/gdb/gdb/regex.h
@@ -1,25 +1,19 @@
/* 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! */
-
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Define number of parens for which we record the beginnings and ends.
This affects how much space the `struct re_registers' type takes up. */
diff --git a/gnu/usr.bin/gdb/gdb/remote-utils.c b/gnu/usr.bin/gdb/gdb/remote-utils.c
new file mode 100644
index 000000000000..f4f25e4c490c
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/remote-utils.c
@@ -0,0 +1,645 @@
+/* Generic support for remote debugging interfaces.
+
+ Copyright 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This file actually contains two distinct logical "packages". They
+ are packaged together in this one file because they are typically
+ used together.
+
+ The first package is an addition to the serial package. The
+ addition provides reading and writing with debugging output and
+ timeouts based on user settable variables. These routines are
+ intended to support serial port based remote backends. These
+ functions are prefixed with sr_.
+
+ The second package is a collection of more or less generic
+ functions for use by remote backends. They support user settable
+ variables for debugging, retries, and the like.
+
+ Todo:
+
+ * a pass through mode a la kermit or telnet.
+ * autobaud.
+ * ask remote to change his baud rate.
+ * put generic load here.
+
+ */
+
+#include <ctype.h>
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "serial.h"
+#include "gdbcore.h" /* for exec_bfd */
+#include "inferior.h" /* for generic_mourn_inferior */
+#include "remote-utils.h"
+
+struct _sr_settings sr_settings = {
+ 4, /* timeout:
+ remote-hms.c had 2
+ remote-bug.c had "with a timeout of 2, we time out waiting for
+ the prompt after an s-record dump."
+
+ remote.c had (2): This was 5 seconds, which is a long time to
+ sit and wait. Unless this is going though some terminal server
+ or multiplexer or other form of hairy serial connection, I
+ would think 2 seconds would be plenty.
+*/
+
+ 10, /* retries */
+ NULL, /* device */
+ NULL, /* descriptor */
+};
+
+struct gr_settings *gr_settings = NULL;
+
+static void
+usage(proto, junk)
+ char *proto;
+ char *junk;
+{
+ if (junk != NULL)
+ fprintf(stderr, "Unrecognized arguments: `%s'.\n", junk);
+
+ /* FIXME-now: service@host? */
+
+ error("Usage: target %s <device <speed <debug>>>\n\
+or target %s <host> <port>\n", proto, proto);
+
+ return;
+}
+
+#define CHECKDONE(p, q) \
+{ \
+ if (q == p) \
+ { \
+ if (*p == '\0') \
+ return; \
+ else \
+ usage(proto, p); \
+ } \
+}
+
+void
+sr_scan_args(proto, args)
+ char *proto;
+ char *args;
+{
+ int n;
+ char *p, *q;
+
+ extern int strtol();
+
+ /* if no args, then nothing to do. */
+ if (args == NULL || *args == '\0')
+ return;
+
+ /* scan off white space. */
+ for (p = args; isspace(*p); ++p) ;;
+
+ /* find end of device name. */
+ for (q = p; *q != '\0' && !isspace(*q); ++q) ;;
+
+ /* check for missing or empty device name. */
+ CHECKDONE(p, q);
+ sr_set_device(savestring(p, q - p));
+
+ /* look for baud rate. */
+ n = strtol(q, &p, 10);
+
+ /* check for missing or empty baud rate. */
+ CHECKDONE(p, q);
+ sr_set_baud_rate(n);
+
+ /* look for debug value. */
+ n = strtol(p, &q, 10);
+
+ /* check for missing or empty debug value. */
+ CHECKDONE(p, q);
+ sr_set_debug(n);
+
+ /* scan off remaining white space. */
+ for (p = q; isspace(*p); ++p) ;;
+
+ /* if not end of string, then there's unrecognized junk. */
+ if (*p != '\0')
+ usage(proto, p);
+
+ return;
+}
+
+void
+gr_generic_checkin()
+{
+ sr_write_cr("");
+ gr_expect_prompt();
+}
+
+void
+gr_open(args, from_tty, gr)
+ char *args;
+ int from_tty;
+ struct gr_settings *gr;
+{
+ target_preopen(from_tty);
+ sr_scan_args(gr->ops->to_shortname, args);
+ unpush_target(gr->ops);
+
+ gr_settings = gr;
+
+ gr_set_dcache(dcache_init(gr->readfunc, gr->writefunc));
+
+ if (sr_get_desc() != NULL)
+ gr_close (0);
+
+ sr_set_desc(SERIAL_OPEN (sr_get_device()));
+ if (!sr_get_desc())
+ perror_with_name((char *) sr_get_device());
+
+ if (SERIAL_SETBAUDRATE(sr_get_desc(), sr_get_baud_rate()) != 0)
+ {
+ SERIAL_CLOSE(sr_get_desc());
+ perror_with_name(sr_get_device());
+ }
+
+ SERIAL_RAW (sr_get_desc());
+
+ /* If there is something sitting in the buffer we might take it as a
+ response to a command, which would be bad. */
+ SERIAL_FLUSH_INPUT (sr_get_desc ());
+
+ /* default retries */
+ if (sr_get_retries() == 0)
+ sr_set_retries(1);
+
+ /* default clear breakpoint function */
+ if (gr_settings->clear_all_breakpoints == NULL)
+ gr_settings->clear_all_breakpoints = remove_breakpoints;
+
+ if (from_tty)
+ printf_filtered ("Remote debugging using `%s' at baud rate of %d\n",
+ sr_get_device(), sr_get_baud_rate());
+
+ push_target(gr->ops);
+ gr_checkin();
+ gr_clear_all_breakpoints ();
+ return;
+}
+
+/* Read a character from the remote system masking it down to 7 bits
+ and doing all the fancy timeout stuff. */
+
+int
+sr_readchar ()
+{
+ int buf;
+
+ buf = SERIAL_READCHAR (sr_get_desc(), sr_get_timeout());
+
+ if (buf == SERIAL_TIMEOUT)
+ error ("Timeout reading from remote system.");
+
+ if (sr_get_debug() > 0)
+ printf ("%c", buf);
+
+ return buf & 0x7f;
+}
+
+int
+sr_pollchar()
+{
+ int buf;
+
+ buf = SERIAL_READCHAR (sr_get_desc(), 0);
+ if (buf == SERIAL_TIMEOUT)
+ buf = 0;
+ if (sr_get_debug() > 0)
+ if (buf)
+ printf ("%c", buf);
+ else
+ printf ("<empty character poll>");
+
+ return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+void
+sr_expect (string)
+ char *string;
+{
+ char *p = string;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ if (sr_readchar () == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ p = string;
+ }
+}
+
+void
+sr_write (a, l)
+ char *a;
+ int l;
+{
+ int i;
+
+ if (SERIAL_WRITE (sr_get_desc(), a, l) != 0)
+ perror_with_name ("sr_write: Error writing to remote");
+
+ if (sr_get_debug() > 0)
+ for (i = 0; i < l; i++)
+ printf ("%c", a[i]);
+
+ return;
+}
+
+void
+sr_write_cr (s)
+ char *s;
+{
+ sr_write (s, strlen (s));
+ sr_write ("\r", 1);
+ return;
+}
+
+int
+sr_timed_read (buf, n)
+ char *buf;
+ int n;
+{
+ int i;
+ char c;
+
+ i = 0;
+ while (i < n)
+ {
+ c = sr_readchar ();
+
+ if (c == 0)
+ return i;
+ buf[i] = c;
+ i++;
+
+ }
+ return i;
+}
+
+/* Get a hex digit from the remote system & return its value. If
+ ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+
+int
+sr_get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+
+ while (1)
+ {
+ ch = sr_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)
+ {
+ gr_expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from the remote and put it in *BYT. Accept any number
+ leading spaces. */
+void
+sr_get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = sr_get_hex_digit (1) << 4;
+ val |= sr_get_hex_digit (0);
+ *byt = val;
+}
+
+/* Read a 32-bit hex word from the remote, preceded by a space */
+long
+sr_get_hex_word ()
+{
+ long val;
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + sr_get_hex_digit (j == 0);
+ return val;
+}
+
+/* Put a command string, in args, out to the remote. The remote is assumed to
+ be in raw mode, all writing/reading done through desc.
+ Ouput from the remote is placed on the users terminal until the
+ prompt from the remote is seen.
+ FIXME: Can't handle commands that take input. */
+
+void
+sr_com (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ sr_check_open ();
+
+ if (!args)
+ return;
+
+ /* Clear all input so only command relative output is displayed */
+
+ sr_write_cr (args);
+ sr_write ("\030", 1);
+ gr_expect_prompt ();
+}
+
+void
+gr_close(quitting)
+ int quitting;
+{
+ gr_clear_all_breakpoints();
+
+ if (sr_is_open())
+ {
+ SERIAL_CLOSE (sr_get_desc());
+ sr_set_desc(NULL);
+ }
+
+ return;
+}
+
+/* gr_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. */
+
+void
+gr_detach(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+ if (sr_is_open())
+ gr_clear_all_breakpoints ();
+
+ pop_target ();
+ if (from_tty)
+ puts_filtered ("Ending remote debugging.\n");
+
+ return;
+}
+
+void
+gr_files_info (ops)
+ struct target_ops *ops;
+{
+ char *file = "nothing";
+
+ if (exec_bfd)
+ file = bfd_get_filename (exec_bfd);
+
+ if (exec_bfd)
+ {
+#ifdef __GO32__
+ printf_filtered ("\tAttached to DOS asynctsr\n");
+#else
+ printf_filtered ("\tAttached to %s at %d baud\n",
+ sr_get_device(), sr_get_baud_rate());
+#endif
+ }
+
+ printf_filtered ("\tand running program %s\n", file);
+ printf_filtered ("\tusing the %s protocol.\n", ops->to_shortname);
+}
+
+void
+gr_mourn ()
+{
+ gr_clear_all_breakpoints ();
+ unpush_target (gr_get_ops());
+ generic_mourn_inferior ();
+}
+
+void
+gr_kill ()
+{
+ return;
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+void
+gr_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote process.");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+ sr_check_open ();
+
+ gr_kill ();
+ gr_clear_all_breakpoints ();
+
+ init_wait_for_inferior ();
+ gr_checkin();
+
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+ proceed (entry_pt, -1, 0);
+}
+
+/* Given a null terminated list of strings LIST, read the input until we find one of
+ them. Return the index of the string found or -1 on error. '?' 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. If PASSTHROUGH is non-zero, then
+ pass non-matching data on. */
+
+int
+gr_multi_scan (list, passthrough)
+ char *list[];
+ int passthrough;
+{
+ char *swallowed = NULL; /* holding area */
+ char *swallowed_p = swallowed; /* Current position in swallowed. */
+ int ch;
+ int ch_handled;
+ int i;
+ int string_count;
+ int max_length;
+ char **plist;
+
+ /* Look through the strings. Count them. Find the largest one so we can
+ allocate a holding area. */
+
+ for (max_length = string_count = i = 0;
+ list[i] != NULL;
+ ++i, ++string_count)
+ {
+ int length = strlen(list[i]);
+
+ if (length > max_length)
+ max_length = length;
+ }
+
+ /* if we have no strings, then something is wrong. */
+ if (string_count == 0)
+ return(-1);
+
+ /* otherwise, we will need a holding area big enough to hold almost two
+ copies of our largest string. */
+ swallowed_p = swallowed = alloca(max_length << 1);
+
+ /* and a list of pointers to current scan points. */
+ plist = (char **) alloca (string_count * sizeof(*plist));
+
+ /* and initialize */
+ for (i = 0; i < string_count; ++i)
+ plist[i] = list[i];
+
+ for (ch = sr_readchar(); /* loop forever */ ; ch = sr_readchar())
+ {
+ QUIT; /* Let user quit and leave process running */
+ ch_handled = 0;
+
+ for (i = 0; i < string_count; ++i)
+ {
+ if (ch == *plist[i] || *plist[i] == '?')
+ {
+ ++plist[i];
+ if (*plist[i] == '\0')
+ return(i);
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+
+ ch_handled = 1;
+ }
+ else
+ plist[i] = list[i];
+ }
+
+ if (!ch_handled)
+ {
+ char *p;
+
+ /* Print out any characters which have been swallowed. */
+ if (passthrough)
+ {
+ for (p = swallowed; p < swallowed_p; ++p)
+ putc (*p, stdout);
+
+ putc (ch, stdout);
+ }
+
+ swallowed_p = swallowed;
+ }
+ }
+#if 0
+ /* Never reached. */
+ return(-1);
+#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
+gr_prepare_to_store ()
+{
+ /* Do nothing, since we assume we can store individual regs */
+}
+
+/* Read a word from remote address ADDR and return it.
+ * This goes through the data cache.
+ */
+int
+gr_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ return dcache_fetch (gr_get_dcache(), addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+ This goes through the data cache. */
+
+void
+gr_store_word (addr, word)
+ CORE_ADDR addr;
+ int word;
+{
+ dcache_poke (gr_get_dcache(), addr, word);
+}
+
+void
+_initialize_sr_support ()
+{
+/* FIXME-now: if target is open when baud changes... */
+ add_show_from_set (add_set_cmd ("remotebaud", no_class,
+ var_zinteger, (char *)&baud_rate,
+ "Set baud rate for remote serial I/O.\n\
+This value is used to set the speed of the serial port when debugging\n\
+using remote targets.", &setlist),
+ &showlist);
+
+/* FIXME-now: if target is open... */
+ add_show_from_set (add_set_cmd ("remotedevice", no_class,
+ var_filename, (char *)&sr_settings.device,
+ "Set device for remote serial I/O.\n\
+This device is used as the serial port when debugging using remote\n\
+targets.", &setlist),
+ &showlist);
+
+ add_com ("remote <command>", class_obscure, sr_com,
+ "Send a command to the remote monitor.");
+
+}
diff --git a/gnu/usr.bin/gdb/gdb/remote-utils.h b/gnu/usr.bin/gdb/gdb/remote-utils.h
new file mode 100644
index 000000000000..59f4d3b3706f
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/remote-utils.h
@@ -0,0 +1,149 @@
+/* Generic support for remote debugging interfaces.
+
+ Copyright 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef REMOTE_UTILS_H
+#define REMOTE_UTILS_H
+
+#include "serial.h"
+#include "target.h"
+#include "dcache.h"
+
+/* Stuff that should be shared (and handled consistently) among the various
+ remote targets. */
+
+struct _sr_settings {
+ unsigned int timeout;
+
+ int retries;
+
+ char *device;
+ serial_t desc;
+
+};
+
+extern struct _sr_settings sr_settings;
+extern int remote_debug;
+extern int baud_rate;
+
+/* get and set debug value. */
+#define sr_get_debug() (remote_debug)
+#define sr_set_debug(newval) (remote_debug = (newval))
+
+/* get and set baud rate. */
+#define sr_get_baud_rate() (baud_rate)
+#define sr_set_baud_rate(newval) (baud_rate = (newval))
+
+/* get and set timeout. */
+#define sr_get_timeout() (sr_settings.timeout)
+#define sr_set_timeout(newval) (sr_settings.timeout = (newval))
+
+/* get and set device. */
+#define sr_get_device() (sr_settings.device)
+#define sr_set_device(newval) \
+{ \
+ if (sr_settings.device) free(sr_settings.device); \
+ sr_settings.device = (newval); \
+}
+
+/* get and set descriptor value. */
+#define sr_get_desc() (sr_settings.desc)
+#define sr_set_desc(newval) (sr_settings.desc = (newval))
+
+/* get and set retries. */
+#define sr_get_retries() (sr_settings.retries)
+#define sr_set_retries(newval) (sr_settings.retries = (newval))
+
+#define sr_is_open() (sr_settings.desc != NULL)
+
+#define sr_check_open() { if (!sr_is_open()) \
+ error ("Remote device not open"); }
+
+struct gr_settings {
+ /* This is our data cache. */
+ DCACHE *dcache;
+ char *prompt;
+ struct target_ops *ops;
+ int (*clear_all_breakpoints)PARAMS((void));
+ memxferfunc readfunc;
+ memxferfunc writefunc;
+ void (*checkin)PARAMS((void));
+};
+
+extern struct gr_settings *gr_settings;
+
+/* get and set dcache. */
+#define gr_get_dcache() (gr_settings->dcache)
+#define gr_set_dcache(newval) (gr_settings->dcache = (newval))
+
+/* get and set prompt. */
+#define gr_get_prompt() (gr_settings->prompt)
+#define gr_set_prompt(newval) (gr_settings->prompt = (newval))
+
+/* get and set ops. */
+#define gr_get_ops() (gr_settings->ops)
+#define gr_set_ops(newval) (gr_settings->ops = (newval))
+
+#define gr_clear_all_breakpoints() ((gr_settings->clear_all_breakpoints)())
+#define gr_checkin() ((gr_settings->checkin)())
+
+/* Keep discarding input until we see the 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 gr_expect_prompt(). Exception: 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 bug_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. */
+
+#define gr_expect_prompt() sr_expect(gr_get_prompt())
+
+int gr_fetch_word PARAMS((CORE_ADDR addr));
+int gr_multi_scan PARAMS((char *list[], int passthrough));
+int sr_get_hex_digit PARAMS((int ignore_space));
+int sr_pollchar PARAMS((void));
+int sr_readchar PARAMS((void));
+int sr_timed_read PARAMS((char *buf, int n));
+long sr_get_hex_word PARAMS((void));
+void gr_close PARAMS((int quitting));
+void gr_create_inferior PARAMS((char *execfile, char *args, char **env));
+void gr_detach PARAMS((char *args, int from_tty));
+void gr_files_info PARAMS((struct target_ops *ops));
+void gr_generic_checkin PARAMS((void));
+void gr_kill PARAMS((void));
+void gr_mourn PARAMS((void));
+void gr_prepare_to_store PARAMS((void));
+void gr_store_word PARAMS((CORE_ADDR addr, int word));
+void sr_expect PARAMS((char *string));
+void sr_get_hex_byte PARAMS((char *byt));
+void sr_scan_args PARAMS((char *proto, char *args));
+void sr_write PARAMS((char *a, int l));
+void sr_write_cr PARAMS((char *s));
+
+void gr_open PARAMS((char *args, int from_tty,
+ struct gr_settings *gr_settings));
+
+
+#endif /* REMOTE_UTILS_H */
diff --git a/gnu/usr.bin/gdb/gdb/remote.c b/gnu/usr.bin/gdb/gdb/remote.c
new file mode 100644
index 000000000000..266d5f389def
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/remote.c
@@ -0,0 +1,1272 @@
+/* Remote target communications for serial-line targets in custom GDB protocol
+ Copyright 1988, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Remote communication protocol.
+
+ 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
+
+ <data> is as follows:
+ 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
+ Can be fewer bytes than requested
+ if able to read only part of the data.
+ 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 (this includes the case
+ where only part of the data was
+ written).
+
+ 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"
+
+ or... TAAn...:r...;n:r...;n...:r...;
+ AA = signal number
+ n... = register number
+ r... = register contents
+ or... WAA The process extited, and AA is
+ the exit status. This is only
+ applicable for certains sorts of
+ targets.
+ or... NAATT;DD;BB Relocate the object file.
+ AA = signal number
+ TT = text address
+ DD = data address
+ BB = bss address
+ This is used by the NLM stub,
+ which is why it only has three
+ addresses rather than one per
+ section: the NLM stub always
+ sees only three sections, even
+ though gdb may see more.
+
+ kill request k
+
+ toggle debug d toggle debug flag (see 386 & 68k stubs)
+ reset r reset -- see sparc stub.
+ reserved <other> On other requests, the stub should
+ ignore the request and send an empty
+ response ($#<checksum>). This way
+ we can extend the protocol and GDB
+ can tell whether the stub it is
+ talking to uses the old or the new.
+*/
+
+#include "defs.h"
+#include <string.h>
+#include <fcntl.h>
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "wait.h"
+#include "terminal.h"
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+
+#include "dcache.h"
+
+#if !defined(DONT_USE_REMOTE)
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <signal.h>
+#include "serial.h"
+
+/* Prototypes for local functions */
+
+static int
+remote_write_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
+
+static int
+remote_read_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
+
+static void
+remote_files_info PARAMS ((struct target_ops *ignore));
+
+static int
+remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
+ int should_write, struct target_ops *target));
+
+static void
+remote_prepare_to_store PARAMS ((void));
+
+static void
+remote_fetch_registers PARAMS ((int regno));
+
+static void
+remote_resume PARAMS ((int pid, int step, int siggnal));
+
+static int
+remote_start_remote PARAMS ((char *dummy));
+
+static void
+remote_open PARAMS ((char *name, int from_tty));
+
+static void
+remote_close PARAMS ((int quitting));
+
+static void
+remote_store_registers PARAMS ((int regno));
+
+static void
+getpkt PARAMS ((char *buf, int forever));
+
+static void
+putpkt PARAMS ((char *buf));
+
+static void
+remote_send PARAMS ((char *buf));
+
+static int
+readchar PARAMS ((void));
+
+static int
+remote_wait PARAMS ((int pid, WAITTYPE *status));
+
+static int
+tohex PARAMS ((int nib));
+
+static int
+fromhex PARAMS ((int a));
+
+static void
+remote_detach PARAMS ((char *args, int from_tty));
+
+static void
+remote_interrupt PARAMS ((int signo));
+
+static void
+remote_interrupt_twice PARAMS ((int signo));
+
+static void
+interrupt_query PARAMS ((void));
+
+extern struct target_ops remote_ops; /* Forward decl */
+
+extern int baud_rate;
+
+extern int remote_debug;
+
+/* This was 5 seconds, which is a long time to sit and wait.
+ Unless this is going though some terminal server or multiplexer or
+ other form of hairy serial connection, I would think 2 seconds would
+ be plenty. */
+static int timeout = 2;
+
+#if 0
+int icache;
+#endif
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so that
+ remote_open knows that we don't have a file open when the program
+ starts. */
+serial_t remote_desc = NULL;
+
+#define PBUFSIZ 1024
+
+/* 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)
+
+/* Round up PBUFSIZ to hold all the registers, at least. */
+#if REGISTER_BYTES > MAXBUFBYTES
+#undef PBUFSIZ
+#define PBUFSIZ (REGISTER_BYTES * 2 + 32)
+#endif
+
+/* Clean up connection to a remote debugger. */
+
+/* ARGSUSED */
+static void
+remote_close (quitting)
+ int quitting;
+{
+ if (remote_desc)
+ SERIAL_CLOSE (remote_desc);
+ remote_desc = NULL;
+}
+
+/* Stub for catch_errors. */
+
+static int
+remote_start_remote (dummy)
+ char *dummy;
+{
+ immediate_quit = 1; /* Allow user to interrupt it */
+
+ /* Ack any packet which the remote side has already sent. */
+ /* I'm not sure this \r is needed; we don't use it any other time we
+ send an ack. */
+ SERIAL_WRITE (remote_desc, "+\r", 2);
+ putpkt ("?"); /* initiate a query from remote machine */
+ immediate_quit = 0;
+
+ start_remote (); /* Initialize gdb process mechanisms */
+ return 1;
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static DCACHE *remote_dcache;
+
+static void
+remote_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ 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).");
+
+ target_preopen (from_tty);
+
+ unpush_target (&remote_ops);
+
+ remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
+
+ remote_desc = SERIAL_OPEN (name);
+ if (!remote_desc)
+ perror_with_name (name);
+
+ if (SERIAL_SETBAUDRATE (remote_desc, baud_rate))
+ {
+ SERIAL_CLOSE (remote_desc);
+ perror_with_name (name);
+ }
+
+ SERIAL_RAW (remote_desc);
+
+ /* If there is something sitting in the buffer we might take it as a
+ response to a command, which would be bad. */
+ SERIAL_FLUSH_INPUT (remote_desc);
+
+ if (from_tty)
+ {
+ puts_filtered ("Remote debugging using ");
+ puts_filtered (name);
+ puts_filtered ("\n");
+ }
+ push_target (&remote_ops); /* Switch to using remote target now */
+
+ /* Start the remote connection; if error (0), discard this target.
+ In particular, if the user quits, be sure to discard it
+ (we'd be in an inconsistent state otherwise). */
+ if (!catch_errors (remote_start_remote, (char *)0,
+ "Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
+ pop_target();
+}
+
+/* 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)
+ puts_filtered ("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;
+}
+
+/* Tell the remote machine to resume. */
+
+static void
+remote_resume (pid, step, siggnal)
+ int pid, step, siggnal;
+{
+ char buf[PBUFSIZ];
+
+ if (siggnal)
+ {
+ char *name;
+ target_terminal_ours_for_output ();
+ printf_filtered ("Can't send signals to a remote system. ");
+ name = strsigno (siggnal);
+ if (name)
+ printf_filtered (name);
+ else
+ printf_filtered ("Signal %d", siggnal);
+ printf_filtered (" not sent.\n");
+ target_terminal_inferior ();
+ }
+
+ dcache_flush (remote_dcache);
+
+ strcpy (buf, step ? "s": "c");
+
+ putpkt (buf);
+}
+
+/* Send ^C to target to halt it. Target will respond, and send us a
+ packet. */
+
+static void
+remote_interrupt (signo)
+ int signo;
+{
+ /* If this doesn't work, try more severe steps. */
+ signal (signo, remote_interrupt_twice);
+
+ if (remote_debug)
+ printf ("remote_interrupt called\n");
+
+ SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */
+}
+
+static void (*ofunc)();
+
+/* The user typed ^C twice. */
+static void
+remote_interrupt_twice (signo)
+ int signo;
+{
+ signal (signo, ofunc);
+
+ interrupt_query ();
+
+ signal (signo, remote_interrupt);
+}
+
+/* Ask the user what to do when an interrupt is received. */
+
+static void
+interrupt_query ()
+{
+ target_terminal_ours ();
+
+ if (query ("Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? "))
+ {
+ target_mourn_inferior ();
+ return_to_top_level (RETURN_QUIT);
+ }
+
+ target_terminal_inferior ();
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would.
+ Returns "pid" (though it's not clear what, if anything, that
+ means in the case of this target). */
+
+static int
+remote_wait (pid, status)
+ int pid;
+ WAITTYPE *status;
+{
+ unsigned char buf[PBUFSIZ];
+
+ WSETEXIT ((*status), 0);
+
+ while (1)
+ {
+ unsigned char *p;
+
+ ofunc = (void (*)()) signal (SIGINT, remote_interrupt);
+ getpkt ((char *) buf, 1);
+ signal (SIGINT, ofunc);
+
+ if (buf[0] == 'E')
+ warning ("Remote failure reply: %s", buf);
+ else if (buf[0] == 'T')
+ {
+ int i;
+ long regno;
+ char regs[MAX_REGISTER_RAW_SIZE];
+
+ /* Expedited reply, containing Signal, {regno, reg} repeat */
+ /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where
+ ss = signal number
+ n... = register number
+ r... = register contents
+ */
+
+ p = &buf[3]; /* after Txx */
+
+ while (*p)
+ {
+ unsigned char *p1;
+
+ regno = strtol (p, &p1, 16); /* Read the register number */
+
+ if (p1 == p)
+ warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n",
+ p1, buf);
+
+ p = p1;
+
+ if (*p++ != ':')
+ warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n",
+ p, buf);
+
+ if (regno >= NUM_REGS)
+ warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n",
+ regno, p, buf);
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
+ {
+ if (p[0] == 0 || p[1] == 0)
+ warning ("Remote reply is too short: %s", buf);
+ regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
+
+ if (*p++ != ';')
+ warning ("Remote register badly formatted: %s", buf);
+
+ supply_register (regno, regs);
+ }
+ break;
+ }
+ else if (buf[0] == 'N')
+ {
+ unsigned char *p1;
+ bfd_vma text_addr, data_addr, bss_addr;
+
+ /* Relocate object file. Format is NAATT;DD;BB where AA is
+ the signal number, TT is the new text address, DD is the
+ new data address, and BB is the new bss address. This is
+ used by the NLM stub; gdb may see more sections. */
+ p = &buf[3];
+ text_addr = strtoul (p, &p1, 16);
+ if (p1 == p || *p1 != ';')
+ warning ("Malformed relocation packet: Packet '%s'", buf);
+ p = p1 + 1;
+ data_addr = strtoul (p, &p1, 16);
+ if (p1 == p || *p1 != ';')
+ warning ("Malformed relocation packet: Packet '%s'", buf);
+ p = p1 + 1;
+ bss_addr = strtoul (p, &p1, 16);
+ if (p1 == p)
+ warning ("Malformed relocation packet: Packet '%s'", buf);
+
+ if (symfile_objfile != NULL
+ && (ANOFFSET (symfile_objfile->section_offsets,
+ SECT_OFF_TEXT) != text_addr
+ || ANOFFSET (symfile_objfile->section_offsets,
+ SECT_OFF_DATA) != data_addr
+ || ANOFFSET (symfile_objfile->section_offsets,
+ SECT_OFF_BSS) != bss_addr))
+ {
+ struct section_offsets *offs;
+
+ /* FIXME: This code assumes gdb-stabs.h is being used;
+ it's broken for xcoff, dwarf, sdb-coff, etc. But
+ there is no simple canonical representation for this
+ stuff. (Just what does "text" as seen by the stub
+ mean, anyway?). */
+
+ /* FIXME: Why don't the various symfile_offsets routines
+ in the sym_fns vectors set this?
+ (no good reason -kingdon). */
+ if (symfile_objfile->num_sections == 0)
+ symfile_objfile->num_sections = SECT_OFF_MAX;
+
+ offs = ((struct section_offsets *)
+ alloca (sizeof (struct section_offsets)
+ + (symfile_objfile->num_sections
+ * sizeof (offs->offsets))));
+ memcpy (offs, symfile_objfile->section_offsets,
+ (sizeof (struct section_offsets)
+ + (symfile_objfile->num_sections
+ * sizeof (offs->offsets))));
+ ANOFFSET (offs, SECT_OFF_TEXT) = text_addr;
+ ANOFFSET (offs, SECT_OFF_DATA) = data_addr;
+ ANOFFSET (offs, SECT_OFF_BSS) = bss_addr;
+
+ objfile_relocate (symfile_objfile, offs);
+ {
+ struct obj_section *s;
+ bfd *abfd;
+
+ abfd = symfile_objfile->obfd;
+
+ for (s = symfile_objfile->sections;
+ s < symfile_objfile->sections_end; ++s)
+ {
+ flagword flags;
+
+ flags = bfd_get_section_flags (abfd, s->sec_ptr);
+
+ if (flags & SEC_CODE)
+ {
+ s->addr += text_addr;
+ s->endaddr += text_addr;
+ }
+ else if (flags & (SEC_DATA | SEC_LOAD))
+ {
+ s->addr += data_addr;
+ s->endaddr += data_addr;
+ }
+ else if (flags & SEC_ALLOC)
+ {
+ s->addr += bss_addr;
+ s->endaddr += bss_addr;
+ }
+ }
+ }
+ }
+ break;
+ }
+ else if (buf[0] == 'W')
+ {
+ /* The remote process exited. */
+ WSETEXIT (*status, (fromhex (buf[1]) << 4) + fromhex (buf[2]));
+ return 0;
+ }
+ else if (buf[0] == 'S')
+ break;
+ else
+ warning ("Invalid remote reply: %s", buf);
+ }
+
+ WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))));
+
+ return 0;
+}
+
+/* Number of bytes of registers this stub implements. */
+static int register_bytes_found;
+
+/* Read the remote registers into the block REGS. */
+/* Currently we just read all the registers, so we don't use regno. */
+/* ARGSUSED */
+static void
+remote_fetch_registers (regno)
+ int regno;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+ char regs[REGISTER_BYTES];
+
+ sprintf (buf, "g");
+ remote_send (buf);
+
+ /* Unimplemented registers read as all bits zero. */
+ memset (regs, 0, REGISTER_BYTES);
+
+ /* We can get out of synch in various cases. If the first character
+ in the buffer is not a hex character, assume that has happened
+ and try to fetch another packet to read. */
+ while ((buf[0] < '0' || buf[0] > '9')
+ && (buf[0] < 'a' || buf[0] > 'f'))
+ {
+ if (remote_debug)
+ printf ("Bad register packet; fetching a new packet\n");
+ getpkt (buf, 0);
+ }
+
+ /* 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)
+ break;
+ if (p[1] == 0)
+ {
+ warning ("Remote reply is of odd length: %s", buf);
+ /* Don't change register_bytes_found in this case, and don't
+ print a second warning. */
+ goto supply_them;
+ }
+ regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
+
+ if (i != register_bytes_found)
+ {
+ register_bytes_found = i;
+#ifdef REGISTER_BYTES_OK
+ if (!REGISTER_BYTES_OK (i))
+ warning ("Remote reply is too short: %s", buf);
+#endif
+ }
+
+ supply_them:
+ for (i = 0; i < NUM_REGS; i++)
+ supply_register (i, &regs[REGISTER_BYTE(i)]);
+}
+
+/* Prepare to store registers. Since we send them all, we have to
+ read out the ones we don't want to change first. */
+
+static void
+remote_prepare_to_store ()
+{
+ /* Make sure the entire registers array is valid. */
+ read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
+}
+
+/* Store the remote registers from the contents of the block REGISTERS.
+ FIXME, eventually just store one register if that's all that is needed. */
+
+/* ARGSUSED */
+static void
+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;
+ /* remote_prepare_to_store insures that register_bytes_found gets set. */
+ for (i = 0; i < register_bytes_found; i++)
+ {
+ *p++ = tohex ((registers[i] >> 4) & 0xf);
+ *p++ = tohex (registers[i] & 0xf);
+ }
+ *p = '\0';
+
+ remote_send (buf);
+}
+
+#if 0
+
+/* Use of the data cache is disabled because it loses for looking at
+ and changing hardware I/O ports and the like. Accepting `volatile'
+ would perhaps be one way to fix it, but a better way which would
+ win for more cases would be to use the executable file for the text
+ segment, like the `icache' code below but done cleanly (in some
+ target-independent place, perhaps in target_xfer_memory, perhaps
+ based on assigning each target a speed or perhaps by some simpler
+ mechanism). */
+
+/* Read a word from remote address ADDR and return it.
+ This goes through the data cache. */
+
+static int
+remote_fetch_word (addr)
+ CORE_ADDR addr;
+{
+#if 0
+ 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;
+ }
+ }
+#endif
+ return dcache_fetch (remote_dcache, addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+ This goes through the data cache. */
+
+static void
+remote_store_word (addr, word)
+ CORE_ADDR addr;
+ int word;
+{
+ dcache_poke (remote_dcache, addr, word);
+}
+#endif /* 0 */
+
+/* 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.
+
+ Returns number of bytes transferred, or 0 for error. */
+
+static int
+remote_write_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+
+ if (len > PBUFSIZ / 2 - 20)
+ abort ();
+
+ sprintf (buf, "M%x,%x:", memaddr, len);
+
+ /* We send target system values byte by byte, in increasing byte addresses,
+ 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';
+
+ putpkt (buf);
+ getpkt (buf, 0);
+
+ if (buf[0] == 'E')
+ {
+ /* There is no correspondance between what the remote protocol uses
+ for errors and errno codes. We would like a cleaner way of
+ representing errors (big enough to include errno codes, bfd_error
+ codes, and others). But for now just return EIO. */
+ errno = EIO;
+ return 0;
+ }
+ return len;
+}
+
+/* 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.
+
+ Returns number of bytes transferred, or 0 for error. */
+
+static int
+remote_read_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+
+ if (len > PBUFSIZ / 2 - 1)
+ abort ();
+
+ sprintf (buf, "m%x,%x", memaddr, len);
+ putpkt (buf);
+ getpkt (buf, 0);
+
+ if (buf[0] == 'E')
+ {
+ /* There is no correspondance between what the remote protocol uses
+ for errors and errno codes. We would like a cleaner way of
+ representing errors (big enough to include errno codes, bfd_error
+ codes, and others). But for now just return EIO. */
+ errno = EIO;
+ return 0;
+ }
+
+ /* Reply describes memory 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)
+ /* Reply is short. This means that we were able to read only part
+ of what we wanted to. */
+ break;
+ myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
+ return i;
+}
+
+/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
+ to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
+ nonzero. Returns length of data written or read; 0 for error. */
+
+/* ARGSUSED */
+static int
+remote_xfer_memory(memaddr, myaddr, len, should_write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+ struct target_ops *target; /* ignored */
+{
+ int xfersize;
+ int bytes_xferred;
+ int total_xferred = 0;
+
+ while (len > 0)
+ {
+ if (len > MAXBUFBYTES)
+ xfersize = MAXBUFBYTES;
+ else
+ xfersize = len;
+
+ if (should_write)
+ bytes_xferred = remote_write_bytes (memaddr, myaddr, xfersize);
+ else
+ bytes_xferred = remote_read_bytes (memaddr, myaddr, xfersize);
+
+ /* If we get an error, we are done xferring. */
+ if (bytes_xferred == 0)
+ break;
+
+ memaddr += bytes_xferred;
+ myaddr += bytes_xferred;
+ len -= bytes_xferred;
+ total_xferred += bytes_xferred;
+ }
+ return total_xferred;
+}
+
+static void
+remote_files_info (ignore)
+ struct target_ops *ignore;
+{
+ puts_filtered ("Debugging a target over a serial line.\n");
+}
+
+/* Stuff for dealing with the packets which are part of this protocol.
+ See comment at top of file for details. */
+
+/* Read a single character from the remote end, masking it down to 7 bits. */
+
+static int
+readchar ()
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (remote_desc, timeout);
+
+ if (ch < 0)
+ return ch;
+
+ return ch & 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, 0);
+
+ 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[PBUFSIZ];
+ int cnt = strlen (buf);
+ int ch;
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ if (cnt > sizeof(buf2) - 5) /* Prosanity check */
+ abort();
+
+ 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. */
+
+ while (1)
+ {
+ if (remote_debug)
+ {
+ *p = '\0';
+ printf ("Sending packet: %s...", buf2); fflush(stdout);
+ }
+ if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
+ perror_with_name ("putpkt: write failed");
+
+ /* read until either a timeout occurs (-2) or '+' is read */
+ while (1)
+ {
+ ch = readchar ();
+
+ switch (ch)
+ {
+ case '+':
+ if (remote_debug)
+ printf("Ack\n");
+ return;
+ case SERIAL_TIMEOUT:
+ break; /* Retransmit buffer */
+ case SERIAL_ERROR:
+ perror_with_name ("putpkt: couldn't read ACK");
+ case SERIAL_EOF:
+ error ("putpkt: EOF while trying to read ACK");
+ default:
+ if (remote_debug)
+ printf ("%02X %c ", ch&0xFF, ch);
+ continue;
+ }
+ break; /* Here to retransmit */
+ }
+
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ interrupt_query ();
+ }
+ }
+}
+
+/* Read a packet from the remote machine, with error checking,
+ and store it in BUF. BUF is expected to be of size PBUFSIZ.
+ If FOREVER, wait forever rather than timing out; this is used
+ while the target is executing user code. */
+
+static void
+getpkt (buf, forever)
+ char *buf;
+ int forever;
+{
+ char *bp;
+ unsigned char csum;
+ int c = 0;
+ unsigned char c1, c2;
+ int retries = 0;
+#define MAX_RETRIES 10
+
+ while (1)
+ {
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ interrupt_query ();
+ }
+
+ /* This can loop forever if the remote side sends us characters
+ continuously, but if it pauses, we'll get a zero from readchar
+ because of timeout. Then we'll count that as a retry. */
+
+ c = readchar();
+ if (c > 0 && c != '$')
+ continue;
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (forever)
+ continue;
+ if (++retries >= MAX_RETRIES)
+ if (remote_debug) puts_filtered ("Timed out.\n");
+ goto out;
+ }
+
+ if (c == SERIAL_EOF)
+ error ("Remote connection closed");
+ if (c == SERIAL_ERROR)
+ perror_with_name ("Remote communication error");
+
+ /* Force csum to be zero here because of possible error retry. */
+ csum = 0;
+ bp = buf;
+
+ while (1)
+ {
+ c = readchar ();
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (remote_debug)
+ puts_filtered ("Timeout in mid-packet, retrying\n");
+ goto whole; /* Start a new packet, count retries */
+ }
+ if (c == '$')
+ {
+ if (remote_debug)
+ puts_filtered ("Saw new packet start in middle of old one\n");
+ goto whole; /* Start a new packet, count retries */
+ }
+ if (c == '#')
+ break;
+ if (bp >= buf+PBUFSIZ-1)
+ {
+ *bp = '\0';
+ puts_filtered ("Remote packet too long: ");
+ puts_filtered (buf);
+ puts_filtered ("\n");
+ goto whole;
+ }
+ *bp++ = c;
+ csum += c;
+ }
+ *bp = 0;
+
+ c1 = fromhex (readchar ());
+ c2 = fromhex (readchar ());
+ if ((csum & 0xff) == (c1 << 4) + c2)
+ break;
+ printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
+ (c1 << 4) + c2, csum & 0xff);
+ puts_filtered (buf);
+ puts_filtered ("\n");
+
+ /* Try the whole thing again. */
+whole:
+ if (++retries < MAX_RETRIES)
+ {
+ SERIAL_WRITE (remote_desc, "-", 1);
+ }
+ else
+ {
+ printf ("Ignoring packet error, continuing...\n");
+ break;
+ }
+ }
+
+out:
+
+ SERIAL_WRITE (remote_desc, "+", 1);
+
+ if (remote_debug)
+ fprintf (stderr,"Packet received: %s\n", buf);
+}
+
+static void
+remote_kill ()
+{
+ putpkt ("k");
+ /* Don't wait for it to die. I'm not really sure it matters whether
+ we do or not. For the existing stubs, kill is a noop. */
+ target_mourn_inferior ();
+}
+
+static void
+remote_mourn ()
+{
+ unpush_target (&remote_ops);
+ generic_mourn_inferior ();
+}
+
+#ifdef REMOTE_BREAKPOINT
+
+/* On some machines, e.g. 68k, we may use a different breakpoint instruction
+ than other targets. */
+static unsigned char break_insn[] = REMOTE_BREAKPOINT;
+
+/* Check that it fits in BREAKPOINT_MAX bytes. */
+static unsigned char check_break_insn_size[BREAKPOINT_MAX] = REMOTE_BREAKPOINT;
+
+#else /* No REMOTE_BREAKPOINT. */
+
+/* Same old breakpoint instruction. This code does nothing different
+ than mem-break.c. */
+static unsigned char break_insn[] = BREAKPOINT;
+
+#endif /* No REMOTE_BREAKPOINT. */
+
+/* Insert a breakpoint on targets 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 (this
+ is accomplished via BREAKPOINT_MAX). */
+
+static int
+remote_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, (char *)break_insn, sizeof break_insn);
+
+ return val;
+}
+
+static int
+remote_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ return target_write_memory (addr, contents_cache, sizeof break_insn);
+}
+
+/* Define the target subroutine names */
+
+struct target_ops remote_ops = {
+ "remote", /* to_shortname */
+ "Remote serial target in gdb-specific protocol", /* to_longname */
+ "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */
+ remote_open, /* to_open */
+ remote_close, /* to_close */
+ NULL, /* to_attach */
+ remote_detach, /* to_detach */
+ remote_resume, /* to_resume */
+ remote_wait, /* to_wait */
+ remote_fetch_registers, /* to_fetch_registers */
+ remote_store_registers, /* to_store_registers */
+ remote_prepare_to_store, /* to_prepare_to_store */
+ remote_xfer_memory, /* to_xfer_memory */
+ remote_files_info, /* to_files_info */
+
+ remote_insert_breakpoint, /* to_insert_breakpoint */
+ remote_remove_breakpoint, /* to_remove_breakpoint */
+
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ remote_kill, /* to_kill */
+ generic_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ NULL, /* to_create_inferior */
+ remote_mourn, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ process_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_remote ()
+{
+ add_target (&remote_ops);
+}
+#endif
diff --git a/gnu/usr.bin/gdb/gdb/ser-unix.c b/gnu/usr.bin/gdb/gdb/ser-unix.c
new file mode 100644
index 000000000000..b306e8ace5b2
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/ser-unix.c
@@ -0,0 +1,633 @@
+/* Serial interface for local (hardwired) serial ports on Un*x like systems
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "serial.h"
+#include <fcntl.h>
+#include <sys/types.h>
+
+#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
+#define HAVE_SGTTY
+#endif
+
+#ifdef HAVE_TERMIOS
+#include <termios.h>
+#include <unistd.h>
+
+struct hardwire_ttystate
+{
+ struct termios termios;
+};
+#endif /* termios */
+
+#ifdef HAVE_TERMIO
+#include <termio.h>
+
+/* It is believed that all systems which have added job control to SVR3
+ (e.g. sco) have also added termios. Even if not, trying to figure out
+ all the variations (TIOCGPGRP vs. TCGETPGRP, etc.) would be pretty
+ bewildering. So we don't attempt it. */
+
+struct hardwire_ttystate
+{
+ struct termio termio;
+};
+#endif /* termio */
+
+#ifdef HAVE_SGTTY
+/* Needed for the code which uses select(). We would include <sys/select.h>
+ too if it existed on all systems. */
+#include <sys/time.h>
+
+#include <sgtty.h>
+
+struct hardwire_ttystate
+{
+ struct sgttyb sgttyb;
+ struct tchars tc;
+ struct ltchars ltc;
+ /* Line discipline flags. */
+ int lmode;
+};
+#endif /* sgtty */
+
+static int hardwire_open PARAMS ((serial_t scb, const char *name));
+static void hardwire_raw PARAMS ((serial_t scb));
+static int wait_for PARAMS ((serial_t scb, int timeout));
+static int hardwire_readchar PARAMS ((serial_t scb, int timeout));
+static int rate_to_code PARAMS ((int rate));
+static int hardwire_setbaudrate PARAMS ((serial_t scb, int rate));
+static int hardwire_write PARAMS ((serial_t scb, const char *str, int len));
+/* FIXME: static void hardwire_restore PARAMS ((serial_t scb)); */
+static void hardwire_close PARAMS ((serial_t scb));
+static int get_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
+static int set_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
+static serial_ttystate hardwire_get_tty_state PARAMS ((serial_t scb));
+static int hardwire_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+
+/* Open up a real live device for serial I/O */
+
+static int
+hardwire_open(scb, name)
+ serial_t scb;
+ const char *name;
+{
+ scb->fd = open (name, O_RDWR);
+ if (scb->fd < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+get_tty_state(scb, state)
+ serial_t scb;
+ struct hardwire_ttystate *state;
+{
+#ifdef HAVE_TERMIOS
+ extern int errno;
+
+ if (tcgetattr(scb->fd, &state->termios) < 0)
+ return -1;
+
+ return 0;
+#endif
+
+#ifdef HAVE_TERMIO
+ if (ioctl (scb->fd, TCGETA, &state->termio) < 0)
+ return -1;
+ return 0;
+#endif
+
+#ifdef HAVE_SGTTY
+ if (ioctl (scb->fd, TIOCGETP, &state->sgttyb) < 0)
+ return -1;
+ if (ioctl (scb->fd, TIOCGETC, &state->tc) < 0)
+ return -1;
+ if (ioctl (scb->fd, TIOCGLTC, &state->ltc) < 0)
+ return -1;
+ if (ioctl (scb->fd, TIOCLGET, &state->lmode) < 0)
+ return -1;
+
+ return 0;
+#endif
+}
+
+static int
+set_tty_state(scb, state)
+ serial_t scb;
+ struct hardwire_ttystate *state;
+{
+#ifdef HAVE_TERMIOS
+ if (tcsetattr(scb->fd, TCSANOW, &state->termios) < 0)
+ return -1;
+
+ return 0;
+#endif
+
+#ifdef HAVE_TERMIO
+ if (ioctl (scb->fd, TCSETA, &state->termio) < 0)
+ return -1;
+ return 0;
+#endif
+
+#ifdef HAVE_SGTTY
+ if (ioctl (scb->fd, TIOCSETN, &state->sgttyb) < 0)
+ return -1;
+
+ return 0;
+#endif
+}
+
+static serial_ttystate
+hardwire_get_tty_state(scb)
+ serial_t scb;
+{
+ struct hardwire_ttystate *state;
+
+ state = (struct hardwire_ttystate *)xmalloc(sizeof *state);
+
+ if (get_tty_state(scb, state))
+ return NULL;
+
+ return (serial_ttystate)state;
+}
+
+static int
+hardwire_set_tty_state(scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ struct hardwire_ttystate *state;
+
+ state = (struct hardwire_ttystate *)ttystate;
+
+ return set_tty_state(scb, state);
+}
+
+static int
+hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ struct hardwire_ttystate new_state;
+ struct hardwire_ttystate *state = (struct hardwire_ttystate *) old_ttystate;
+
+ new_state = *(struct hardwire_ttystate *)new_ttystate;
+
+#ifdef HAVE_TERMIOS
+ /* I'm not sure whether this is necessary; the manpage makes no mention
+ of discarding input when switching to/from ICANON. */
+ if (state->termios.c_lflag & ICANON)
+ new_state.termios.c_lflag |= ICANON;
+ else
+ new_state.termios.c_lflag &= ~ICANON;
+#endif
+
+#ifdef HAVE_TERMIO
+ /* I'm not sure whether this is necessary; the manpage makes no mention
+ of discarding input when switching to/from ICANON. */
+ if (state->termio.c_lflag & ICANON)
+ new_state.termio.c_lflag |= ICANON;
+ else
+ new_state.termio.c_lflag &= ~ICANON;
+#endif
+
+#ifdef HAVE_SGTTY
+ if (state->sgttyb.sg_flags & RAW)
+ new_state.sgttyb.sg_flags |= RAW;
+ else
+ new_state.sgttyb.sg_flags &= ~RAW;
+
+ /* I'm not sure whether this is necessary; the manpage just mentions
+ RAW not CBREAK. */
+ if (state->sgttyb.sg_flags & CBREAK)
+ new_state.sgttyb.sg_flags |= CBREAK;
+ else
+ new_state.sgttyb.sg_flags &= ~CBREAK;
+#endif
+
+ return set_tty_state (scb, &new_state);
+}
+
+static void
+hardwire_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ struct hardwire_ttystate *state = (struct hardwire_ttystate *) ttystate;
+ int i;
+
+#ifdef HAVE_TERMIOS
+ printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
+ state->termios.c_iflag, state->termios.c_oflag);
+ printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x\n",
+ state->termios.c_cflag, state->termios.c_lflag);
+#if 0
+ /* This not in POSIX, and is not really documented by those systems
+ which have it (at least not Sun). */
+ printf_filtered ("c_line = 0x%x.\n", state->termios.c_line);
+#endif
+ printf_filtered ("c_cc: ");
+ for (i = 0; i < NCCS; i += 1)
+ printf_filtered ("0x%x ", state->termios.c_cc[i]);
+ printf_filtered ("\n");
+#endif
+
+#ifdef HAVE_TERMIO
+ printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
+ state->termio.c_iflag, state->termio.c_oflag);
+ printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
+ state->termio.c_cflag, state->termio.c_lflag,
+ state->termio.c_line);
+ printf_filtered ("c_cc: ");
+ for (i = 0; i < NCC; i += 1)
+ printf_filtered ("0x%x ", state->termio.c_cc[i]);
+ printf_filtered ("\n");
+#endif
+
+#ifdef HAVE_SGTTY
+ printf_filtered ("sgttyb.sg_flags = 0x%x.\n", state->sgttyb.sg_flags);
+
+ printf_filtered ("tchars: ");
+ for (i = 0; i < (int)sizeof (struct tchars); i++)
+ printf_filtered ("0x%x ", ((unsigned char *)&state->tc)[i]);
+ printf_filtered ("\n");
+
+ printf_filtered ("ltchars: ");
+ for (i = 0; i < (int)sizeof (struct ltchars); i++)
+ printf_filtered ("0x%x ", ((unsigned char *)&state->ltc)[i]);
+ printf_filtered ("\n");
+
+ printf_filtered ("lmode: 0x%x\n", state->lmode);
+#endif
+}
+
+static int
+hardwire_flush_output (scb)
+ serial_t scb;
+{
+#ifdef HAVE_TERMIOS
+ return tcflush (scb->fd, TCOFLUSH);
+#endif
+
+#ifdef HAVE_TERMIO
+ return ioctl (scb->fd, TCFLSH, 1);
+#endif
+
+#ifdef HAVE_SGTTY
+ /* This flushes both input and output, but we can't do better. */
+ return ioctl (scb->fd, TIOCFLUSH, 0);
+#endif
+}
+
+static int
+hardwire_flush_input (scb)
+ serial_t scb;
+{
+#ifdef HAVE_TERMIOS
+ return tcflush (scb->fd, TCIFLUSH);
+#endif
+
+#ifdef HAVE_TERMIO
+ return ioctl (scb->fd, TCFLSH, 0);
+#endif
+
+#ifdef HAVE_SGTTY
+ /* This flushes both input and output, but we can't do better. */
+ return ioctl (scb->fd, TIOCFLUSH, 0);
+#endif
+}
+
+static int
+hardwire_send_break (scb)
+ serial_t scb;
+{
+#ifdef HAVE_TERMIOS
+ return tcsendbreak (scb->fd, 0);
+#endif
+
+#ifdef HAVE_TERMIO
+ return ioctl (scb->fd, TCSBRK, 0);
+#endif
+
+#ifdef HAVE_SGTTY
+ {
+ int status;
+ struct timeval timeout;
+
+ status = ioctl (scb->fd, TIOCSBRK, 0);
+
+ /* Can't use usleep; it doesn't exist in BSD 4.2. */
+ /* Note that if this select() is interrupted by a signal it will not wait
+ the full length of time. I think that is OK. */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 250000;
+ select (0, 0, 0, 0, &timeout);
+ status = ioctl (scb->fd, TIOCCBRK, 0);
+ return status;
+ }
+#endif
+}
+
+static void
+hardwire_raw(scb)
+ serial_t scb;
+{
+ struct hardwire_ttystate state;
+
+ if (get_tty_state(scb, &state))
+ fprintf(stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
+
+#ifdef HAVE_TERMIOS
+ state.termios.c_iflag = 0;
+ state.termios.c_oflag = 0;
+ state.termios.c_lflag = 0;
+ state.termios.c_cflag &= ~(CSIZE|PARENB);
+ state.termios.c_cflag |= CS8;
+ state.termios.c_cc[VMIN] = 0;
+ state.termios.c_cc[VTIME] = 0;
+#endif
+
+#ifdef HAVE_TERMIO
+ state.termio.c_iflag = 0;
+ state.termio.c_oflag = 0;
+ state.termio.c_lflag = 0;
+ state.termio.c_cflag &= ~(CSIZE|PARENB);
+ state.termio.c_cflag |= CS8;
+ state.termio.c_cc[VMIN] = 0;
+ state.termio.c_cc[VTIME] = 0;
+#endif
+
+#ifdef HAVE_SGTTY
+ state.sgttyb.sg_flags |= RAW | ANYP;
+ state.sgttyb.sg_flags &= ~(CBREAK | ECHO);
+#endif
+
+ scb->current_timeout = 0;
+
+ if (set_tty_state (scb, &state))
+ fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
+}
+
+/* Wait for input on scb, with timeout seconds. Returns 0 on success,
+ otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
+
+ For termio{s}, we actually just setup VTIME if necessary, and let the
+ timeout occur in the read() in hardwire_read().
+ */
+
+static int
+wait_for(scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+#ifdef HAVE_SGTTY
+ struct timeval tv;
+ fd_set readfds;
+
+ FD_ZERO (&readfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_SET(scb->fd, &readfds);
+
+ while (1)
+ {
+ int numfds;
+
+ if (timeout >= 0)
+ numfds = select(scb->fd+1, &readfds, 0, 0, &tv);
+ else
+ numfds = select(scb->fd+1, &readfds, 0, 0, 0);
+
+ if (numfds <= 0)
+ if (numfds == 0)
+ return SERIAL_TIMEOUT;
+ else if (errno == EINTR)
+ continue;
+ else
+ return SERIAL_ERROR; /* Got an error from select or poll */
+
+ return 0;
+ }
+
+#endif /* HAVE_SGTTY */
+
+#if defined HAVE_TERMIO || defined HAVE_TERMIOS
+ if (timeout == scb->current_timeout)
+ return 0;
+
+ {
+ struct hardwire_ttystate state;
+
+ if (get_tty_state(scb, &state))
+ fprintf(stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
+
+#ifdef HAVE_TERMIOS
+ state.termios.c_cc[VTIME] = timeout * 10;
+#endif
+
+#ifdef HAVE_TERMIO
+ state.termio.c_cc[VTIME] = timeout * 10;
+#endif
+
+ scb->current_timeout = timeout;
+
+ if (set_tty_state (scb, &state))
+ fprintf(stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
+
+ return 0;
+ }
+#endif /* HAVE_TERMIO || HAVE_TERMIOS */
+}
+
+/* Read a character with user-specified timeout. TIMEOUT is number of seconds
+ to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
+ char if successful. Returns SERIAL_TIMEOUT if timeout expired, EOF if line
+ dropped dead, or SERIAL_ERROR for any other error (see errno in that case). */
+
+static int
+hardwire_readchar(scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int status;
+
+ if (scb->bufcnt-- > 0)
+ return *scb->bufp++;
+
+ status = wait_for(scb, timeout);
+
+ if (status < 0)
+ return status;
+
+ scb->bufcnt = read(scb->fd, scb->buf, BUFSIZ);
+
+ if (scb->bufcnt <= 0)
+ if (scb->bufcnt == 0)
+ return SERIAL_TIMEOUT; /* 0 chars means timeout [may need to
+ distinguish between EOF & timeouts
+ someday] */
+ else
+ return SERIAL_ERROR; /* Got an error from read */
+
+ scb->bufcnt--;
+ scb->bufp = scb->buf;
+ return *scb->bufp++;
+}
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+static struct
+{
+ int rate;
+ int code;
+}
+baudtab[] =
+{
+ {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},
+};
+
+static int
+rate_to_code(rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate)
+ return baudtab[i].code;
+
+ return -1;
+}
+
+static int
+hardwire_setbaudrate(scb, rate)
+ serial_t scb;
+ int rate;
+{
+ struct hardwire_ttystate state;
+
+ if (get_tty_state(scb, &state))
+ return -1;
+
+#ifdef HAVE_TERMIOS
+ cfsetospeed (&state.termios, rate_to_code (rate));
+ cfsetispeed (&state.termios, rate_to_code (rate));
+#endif
+
+#ifdef HAVE_TERMIO
+#ifndef CIBAUD
+#define CIBAUD CBAUD
+#endif
+
+ state.termio.c_cflag &= ~(CBAUD | CIBAUD);
+ state.termio.c_cflag |= rate_to_code (rate);
+#endif
+
+#ifdef HAVE_SGTTY
+ state.sgttyb.sg_ispeed = rate_to_code (rate);
+ state.sgttyb.sg_ospeed = rate_to_code (rate);
+#endif
+
+ return set_tty_state (scb, &state);
+}
+
+static int
+hardwire_write(scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ int cc;
+
+ while (len > 0)
+ {
+ cc = write(scb->fd, str, len);
+
+ if (cc < 0)
+ return 1;
+ len -= cc;
+ str += cc;
+ }
+ return 0;
+}
+
+static void
+hardwire_close(scb)
+ serial_t scb;
+{
+ if (scb->fd < 0)
+ return;
+
+ close(scb->fd);
+ scb->fd = -1;
+}
+
+static struct serial_ops hardwire_ops =
+{
+ "hardwire",
+ 0,
+ hardwire_open,
+ hardwire_close,
+ hardwire_readchar,
+ hardwire_write,
+ hardwire_flush_output,
+ hardwire_flush_input,
+ hardwire_send_break,
+ hardwire_raw,
+ hardwire_get_tty_state,
+ hardwire_set_tty_state,
+ hardwire_print_tty_state,
+ hardwire_noflush_set_tty_state,
+ hardwire_setbaudrate,
+};
+
+void
+_initialize_ser_hardwire ()
+{
+ serial_add_interface (&hardwire_ops);
+}
diff --git a/gnu/usr.bin/gdb/gdb/serial.c b/gnu/usr.bin/gdb/gdb/serial.c
new file mode 100644
index 000000000000..6913fd6e2398
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/serial.c
@@ -0,0 +1,261 @@
+/* Generic serial interface routines
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "serial.h"
+
+/* Linked list of serial I/O handlers */
+
+static struct serial_ops *serial_ops_list = NULL;
+
+/* This is the last serial stream opened. Used by connect command. */
+
+static serial_t last_serial_opened = NULL;
+
+static struct serial_ops *
+serial_interface_lookup (name)
+ char *name;
+{
+ struct serial_ops *ops;
+
+ for (ops = serial_ops_list; ops; ops = ops->next)
+ if (strcmp (name, ops->name) == 0)
+ return ops;
+
+ return NULL;
+}
+
+void
+serial_add_interface(optable)
+ struct serial_ops *optable;
+{
+ optable->next = serial_ops_list;
+ serial_ops_list = optable;
+}
+
+/* Open up a device or a network socket, depending upon the syntax of NAME. */
+
+serial_t
+serial_open(name)
+ const char *name;
+{
+ serial_t scb;
+ struct serial_ops *ops;
+
+ if (strchr (name, ':'))
+ ops = serial_interface_lookup ("tcp");
+ else
+ ops = serial_interface_lookup ("hardwire");
+
+ if (!ops)
+ return NULL;
+
+ scb = (serial_t)xmalloc (sizeof (struct _serial_t));
+
+ scb->ops = ops;
+
+ scb->bufcnt = 0;
+ scb->bufp = scb->buf;
+
+ if (scb->ops->open(scb, name))
+ {
+ free (scb);
+ return NULL;
+ }
+
+ last_serial_opened = scb;
+
+ return scb;
+}
+
+serial_t
+serial_fdopen(fd)
+ const int fd;
+{
+ serial_t scb;
+ struct serial_ops *ops;
+
+ ops = serial_interface_lookup ("hardwire");
+
+ if (!ops)
+ return NULL;
+
+ scb = (serial_t)xmalloc (sizeof (struct _serial_t));
+
+ scb->ops = ops;
+
+ scb->bufcnt = 0;
+ scb->bufp = scb->buf;
+
+ scb->fd = fd;
+
+ last_serial_opened = scb;
+
+ return scb;
+}
+
+void
+serial_close(scb)
+ serial_t scb;
+{
+ last_serial_opened = NULL;
+
+/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
+ should fix your code instead. */
+
+ if (!scb)
+ return;
+
+ scb->ops->close(scb);
+ free(scb);
+}
+
+#if 0
+/*
+The connect command is #if 0 because I hadn't thought of an elegant
+way to wait for I/O on two serial_t's simultaneously. Two solutions
+came to mind:
+
+ 1) Fork, and have have one fork handle the to user direction,
+ and have the other hand the to target direction. This
+ obviously won't cut it for MSDOS.
+
+ 2) Use something like select. This assumes that stdin and
+ the target side can both be waited on via the same
+ mechanism. This may not be true for DOS, if GDB is
+ talking to the target via a TCP socket.
+-grossman, 8 Jun 93
+*/
+
+/* Connect the user directly to the remote system. This command acts just like
+ the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
+
+static serial_t tty_desc; /* Controlling terminal */
+
+static void
+cleanup_tty(ttystate)
+ serial_ttystate ttystate;
+{
+ printf ("\r\n[Exiting connect mode]\r\n");
+ SERIAL_SET_TTY_STATE (tty_desc, ttystate);
+ free (ttystate);
+ SERIAL_CLOSE (tty_desc);
+}
+
+static void
+connect_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ int c;
+ char cur_esc = 0;
+ serial_ttystate ttystate;
+ serial_t port_desc; /* TTY port */
+
+ dont_repeat();
+
+ if (args)
+ fprintf(stderr, "This command takes no args. They have been ignored.\n");
+
+ printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
+
+ tty_desc = SERIAL_FDOPEN (0);
+ port_desc = last_serial_opened;
+
+ ttystate = SERIAL_GET_TTY_STATE (tty_desc);
+
+ SERIAL_RAW (tty_desc);
+ SERIAL_RAW (port_desc);
+
+ make_cleanup (cleanup_tty, ttystate);
+
+ while (1)
+ {
+ int mask;
+
+ mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
+
+ if (mask & 2)
+ { /* tty input */
+ char cx;
+
+ while (1)
+ {
+ c = SERIAL_READCHAR(tty_desc, 0);
+
+ if (c == SERIAL_TIMEOUT)
+ break;
+
+ if (c < 0)
+ perror_with_name("connect");
+
+ cx = c;
+ SERIAL_WRITE(port_desc, &cx, 1);
+
+ switch (cur_esc)
+ {
+ case 0:
+ if (c == '\r')
+ cur_esc = c;
+ break;
+ case '\r':
+ if (c == '~')
+ cur_esc = c;
+ else
+ cur_esc = 0;
+ break;
+ case '~':
+ if (c == '.' || c == '\004')
+ return;
+ else
+ cur_esc = 0;
+ }
+ }
+ }
+
+ if (mask & 1)
+ { /* Port input */
+ char cx;
+
+ while (1)
+ {
+ c = SERIAL_READCHAR(port_desc, 0);
+
+ if (c == SERIAL_TIMEOUT)
+ break;
+
+ if (c < 0)
+ perror_with_name("connect");
+
+ cx = c;
+
+ SERIAL_WRITE(tty_desc, &cx, 1);
+ }
+ }
+ }
+}
+
+void
+_initialize_serial ()
+{
+ add_com ("connect", class_obscure, connect_command,
+ "Connect the terminal directly up to the command monitor.\n\
+Use <CR>~. or <CR>~^D to break out.");
+}
+#endif /* 0 */
diff --git a/gnu/usr.bin/gdb/gdb/serial.h b/gnu/usr.bin/gdb/gdb/serial.h
new file mode 100644
index 000000000000..7e7e53066864
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/serial.h
@@ -0,0 +1,153 @@
+/* Remote serial support interface definitions for GDB, the GNU Debugger.
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef SERIAL_H
+#define SERIAL_H
+
+/* Terminal state pointer. This is specific to each type of interface. */
+
+typedef PTR serial_ttystate;
+
+struct _serial_t
+{
+ int fd; /* File descriptor */
+ struct serial_ops *ops; /* Function vector */
+ serial_ttystate ttystate; /* Not used (yet) */
+ int bufcnt; /* Amount of data in receive buffer */
+ unsigned char *bufp; /* Current byte */
+ unsigned char buf[BUFSIZ]; /* Da buffer itself */
+ int current_timeout; /* (termio{s} only), last value of VTIME */
+};
+
+typedef struct _serial_t *serial_t;
+
+struct serial_ops {
+ char *name;
+ struct serial_ops *next;
+ int (*open) PARAMS ((serial_t, const char *name));
+ void (*close) PARAMS ((serial_t));
+ int (*readchar) PARAMS ((serial_t, int timeout));
+ int (*write) PARAMS ((serial_t, const char *str, int len));
+ int (*flush_output) PARAMS ((serial_t));
+ int (*flush_input) PARAMS ((serial_t));
+ int (*send_break) PARAMS ((serial_t));
+ void (*go_raw) PARAMS ((serial_t));
+ serial_ttystate (*get_tty_state) PARAMS ((serial_t));
+ int (*set_tty_state) PARAMS ((serial_t, serial_ttystate));
+ void (*print_tty_state) PARAMS ((serial_t, serial_ttystate));
+ int (*noflush_set_tty_state)
+ PARAMS ((serial_t, serial_ttystate, serial_ttystate));
+ int (*setbaudrate) PARAMS ((serial_t, int rate));
+};
+
+/* Add a new serial interface to the interface list */
+
+void serial_add_interface PARAMS ((struct serial_ops *optable));
+
+serial_t serial_open PARAMS ((const char *name));
+
+serial_t serial_fdopen PARAMS ((int fd));
+
+/* For most routines, if a failure is indicated, then errno should be
+ examined. */
+
+/* Try to open NAME. Returns a new serial_t on success, NULL on failure.
+ */
+
+#define SERIAL_OPEN(NAME) serial_open(NAME)
+
+/* Open a new serial stream using a file handle. */
+
+#define SERIAL_FDOPEN(FD) serial_fdopen(FD)
+
+/* Flush pending output. Might also flush input (if this system can't flush
+ only output). */
+
+#define SERIAL_FLUSH_OUTPUT(SERIAL_T) \
+ ((SERIAL_T)->ops->flush_output((SERIAL_T)))
+
+/* Flush pending input. Might also flush output (if this system can't flush
+ only input). */
+
+#define SERIAL_FLUSH_INPUT(SERIAL_T)\
+ ((*(SERIAL_T)->ops->flush_input) ((SERIAL_T)))
+
+/* Send a break between 0.25 and 0.5 seconds long. */
+
+#define SERIAL_SEND_BREAK(SERIAL_T) \
+ ((*(SERIAL_T)->ops->send_break) (SERIAL_T))
+
+/* Turn the port into raw mode. */
+
+#define SERIAL_RAW(SERIAL_T) (SERIAL_T)->ops->go_raw((SERIAL_T))
+
+/* Return a pointer to a newly malloc'd ttystate containing the state
+ of the tty. */
+#define SERIAL_GET_TTY_STATE(SERIAL_T) (SERIAL_T)->ops->get_tty_state((SERIAL_T))
+
+/* Set the state of the tty to TTYSTATE. The change is immediate.
+ When changing to or from raw mode, input might be discarded. */
+#define SERIAL_SET_TTY_STATE(SERIAL_T, TTYSTATE) (SERIAL_T)->ops->set_tty_state((SERIAL_T), (TTYSTATE))
+
+/* printf_filtered a user-comprehensible description of ttystate. */
+#define SERIAL_PRINT_TTY_STATE(SERIAL_T, TTYSTATE) \
+ ((*((SERIAL_T)->ops->print_tty_state)) ((SERIAL_T), (TTYSTATE)))
+
+/* Set the tty state to NEW_TTYSTATE, where OLD_TTYSTATE is the
+ current state (generally obtained from a recent call to
+ SERIAL_GET_TTY_STATE), but be careful not to discard any input.
+ This means that we never switch in or out of raw mode, even
+ if NEW_TTYSTATE specifies a switch. */
+#define SERIAL_NOFLUSH_SET_TTY_STATE(SERIAL_T, NEW_TTYSTATE, OLD_TTYSTATE) \
+ ((*((SERIAL_T)->ops->noflush_set_tty_state)) \
+ ((SERIAL_T), (NEW_TTYSTATE), (OLD_TTYSTATE)))
+
+/* Read one char from the serial device with TIMEOUT seconds to wait
+ or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
+ char if ok, else one of the following codes. Note that all error
+ codes are guaranteed to be < 0. */
+
+#define SERIAL_ERROR -1 /* General error, see errno for details */
+#define SERIAL_TIMEOUT -2
+#define SERIAL_EOF -3
+
+#define SERIAL_READCHAR(SERIAL_T, TIMEOUT) ((SERIAL_T)->ops->readchar((SERIAL_T), TIMEOUT))
+
+/* Set the baudrate to the decimal value supplied. Returns 0 for success,
+ -1 for failure. */
+
+#define SERIAL_SETBAUDRATE(SERIAL_T, RATE) ((SERIAL_T)->ops->setbaudrate((SERIAL_T), RATE))
+
+/* Write LEN chars from STRING to the port SERIAL_T. Returns 0 for
+ success, non-zero for failure. */
+
+#define SERIAL_WRITE(SERIAL_T, STRING, LEN) ((SERIAL_T)->ops->write((SERIAL_T), STRING, LEN))
+
+/* Push out all buffers, close the device and destroy SERIAL_T. */
+
+void serial_close PARAMS ((serial_t));
+
+#define SERIAL_CLOSE(SERIAL_T) serial_close(SERIAL_T)
+
+/* Destroy SERIAL_T without doing the rest of the stuff that SERIAL_CLOSE
+ does. */
+
+#define SERIAL_UN_FDOPEN(SERIAL_T) (free (SERIAL_T))
+
+#endif /* SERIAL_H */
diff --git a/gnu/usr.bin/gdb/gdb/signals.h b/gnu/usr.bin/gdb/gdb/signals.h
new file mode 100644
index 000000000000..08fa606ef097
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/signals.h
@@ -0,0 +1,27 @@
+/* Signal handler definitions for GDB, the GNU Debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 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). */
+/* This has been superceded by the job_control variable in serial.h. */
+
+#include <signal.h>
diff --git a/gnu/usr.bin/gdb/gdb/solib.h b/gnu/usr.bin/gdb/gdb/solib.h
new file mode 100644
index 000000000000..ddabf7460bc1
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/solib.h
@@ -0,0 +1,56 @@
+/* Shared library declarations for GDB, the GNU Debugger.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct target_ops;
+#endif
+
+/* Called when we free all symtabs, to free the shared library information
+ as well. */
+
+#define CLEAR_SOLIB clear_solib
+
+extern void
+clear_solib PARAMS ((void));
+
+/* Called to add symbols from a shared library to gdb's symbol table. */
+
+#define SOLIB_ADD(filename, from_tty, targ) \
+ solib_add (filename, from_tty, targ)
+
+extern void
+solib_add PARAMS ((char *, int, struct target_ops *));
+
+/* Function to be called when the inferior starts up, to discover the names
+ of shared libraries that are dynamically linked, the base addresses to
+ which they are linked, and sufficient information to read in their symbols
+ at a later time. */
+
+#define SOLIB_CREATE_INFERIOR_HOOK(PID) solib_create_inferior_hook()
+
+extern void
+solib_create_inferior_hook PARAMS((void)); /* solib.c */
+
+/* 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 PARAMS ((CORE_ADDR)); /* solib.c */
diff --git a/gnu/usr.bin/gdb/gdb/source.c b/gnu/usr.bin/gdb/gdb/source.c
new file mode 100644
index 000000000000..88781d7cbc91
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/source.c
@@ -0,0 +1,1398 @@
+/* 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.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "expression.h"
+#include "language.h"
+#include "command.h"
+#include "gdbcmd.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"
+#include "regex.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+/* Prototypes for local functions. */
+
+static int
+open_source_file PARAMS ((struct symtab *));
+
+static int
+get_filename_and_charpos PARAMS ((struct symtab *, char **));
+
+static void
+reverse_search_command PARAMS ((char *, int));
+
+static void
+forward_search_command PARAMS ((char *, int));
+
+static void
+line_info PARAMS ((char *, int));
+
+static void
+list_command PARAMS ((char *, int));
+
+static void
+ambiguous_line_spec PARAMS ((struct symtabs_and_lines *));
+
+static void
+source_info PARAMS ((char *, int));
+
+static void
+show_directories PARAMS ((char *, int));
+
+static void
+find_source_lines PARAMS ((struct symtab *, int));
+
+/* If we use this declaration, it breaks because of fucking ANSI "const" stuff
+ on some systems. We just have to not declare it at all, have it default
+ to int, and possibly botch on a few systems. Thanks, ANSIholes... */
+/* extern char *strstr(); */
+
+/* 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;
+
+/* Default 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 = 10;
+
+/* 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;
+
+
+/* Set the source file default for the "list" command to be S.
+
+ If S is NULL, and we don't have a default, find one. This
+ should only be called when the user actually tries to use the
+ default, since we produce an error if we can't find a reasonable
+ default. Also, since this can cause symbols to be read, doing it
+ before we need to would make things slower than necessary. */
+
+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;
+ struct objfile *ofp;
+
+ if (s)
+ {
+ current_source_symtab = s;
+ current_source_line = 1;
+ return;
+ }
+
+ if (current_source_symtab)
+ 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);
+ if (current_source_symtab)
+ return;
+ }
+
+ /* All right; find the last file in the symtab list (ignoring .h's). */
+
+ current_source_line = 1;
+
+ for (ofp = object_files; ofp != NULL; ofp = ofp -> next)
+ {
+ for (s = ofp -> symtabs; s; s = s->next)
+ {
+ char *name = s -> filename;
+ int len = strlen (name);
+ if (! (len > 2 && (STREQ (&name[len - 2], ".h"))))
+ {
+ current_source_symtab = s;
+ }
+ }
+ }
+ if (current_source_symtab)
+ return;
+
+ /* Howabout the partial symbol tables? */
+
+ for (ofp = object_files; ofp != NULL; ofp = ofp -> next)
+ {
+ for (ps = ofp -> psymtabs; ps != NULL; ps = ps -> next)
+ {
+ char *name = ps -> filename;
+ int len = strlen (name);
+ if (! (len > 2 && (STREQ (&name[len - 2], ".h"))))
+ {
+ cs_pst = ps;
+ }
+ }
+ }
+ 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);
+ }
+ }
+
+ error ("Can't find a default source file");
+}
+
+static void
+show_directories (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ puts_filtered ("Source directories searched: ");
+ puts_filtered (source_path);
+ puts_filtered ("\n");
+}
+
+/* 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;
+ register struct objfile *objfile;
+
+ for (objfile = object_files; objfile != NULL; objfile = objfile -> next)
+ {
+ for (s = objfile -> symtabs; s != NULL; s = s -> next)
+ {
+ if (s -> line_charpos != NULL)
+ {
+ mfree (objfile -> md, s -> line_charpos);
+ s -> line_charpos = NULL;
+ }
+ if (s -> fullname != NULL)
+ {
+ mfree (objfile -> md, s -> fullname);
+ s -> fullname = NULL;
+ }
+ }
+ }
+}
+
+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, &source_path);
+ if (from_tty)
+ show_directories ((char *)0, from_tty);
+ forget_cached_source_info ();
+}
+
+/* Add zero or more directories to the front of an arbitrary path. */
+
+void
+mod_path (dirname, which_path)
+ char *dirname;
+ char **which_path;
+{
+ char *old = *which_path;
+ int prefix = 0;
+
+ if (dirname == 0)
+ return;
+
+ dirname = strsave (dirname);
+ make_cleanup (free, dirname);
+
+ do
+ {
+ char *name = dirname;
+ register char *p;
+ struct stat st;
+
+ {
+ char *colon = strchr (name, ':');
+ char *space = strchr (name, ' ');
+ char *tab = strchr (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, NULL);
+ else
+ name = savestring (name, p - name);
+ make_cleanup (free, name);
+
+ /* Unless it's a variable, check existence. */
+ if (name[0] != '$') {
+ /* These are warnings, not errors, since we don't want a
+ non-existent directory in a .gdbinit file to stop processing
+ of the .gdbinit file.
+
+ Whether they get added to the path is more debatable. Current
+ answer is yes, in case the user wants to go make the directory
+ or whatever. If the directory continues to not exist/not be
+ a directory/etc, then having them in the path should be
+ harmless. */
+ if (stat (name, &st) < 0)
+ {
+ int save_errno = errno;
+ fprintf (stderr, "Warning: ");
+ print_sys_errmsg (name, save_errno);
+ }
+ else if ((st.st_mode & S_IFMT) != S_IFDIR)
+ warning ("%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 = strchr (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, NULL);
+ old[prefix] = c;
+ *which_path = concat (temp, "", &old[prefix], NULL);
+ prefix = strlen (temp);
+ free (temp);
+ }
+ else
+ {
+ *which_path = concat (name, (old[0]? ":" : old), old, NULL);
+ prefix = strlen (name);
+ }
+ free (old);
+ old = *which_path;
+ }
+ }
+ skip_dup: ;
+ } while (*dirname != '\0');
+}
+
+
+static void
+source_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct symtab *s = current_source_symtab;
+
+ if (!s)
+ {
+ printf_filtered("No current source file.\n");
+ return;
+ }
+ printf_filtered ("Current source file is %s\n", s->filename);
+ if (s->dirname)
+ printf_filtered ("Compilation directory is %s\n", s->dirname);
+ if (s->fullname)
+ printf_filtered ("Located in %s\n", s->fullname);
+ if (s->nlines)
+ printf_filtered ("Contains %d line%s.\n", s->nlines,
+ s->nlines == 1 ? "" : "s");
+
+ printf_filtered("Source language is %s.\n", language_str (s->language));
+}
+
+
+
+/* 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 "."). This also indicates
+ that a slash in STRING disables searching of the path (this is
+ so that "exec-file ./foo" or "symbol-file ./foo" insures that you
+ get that particular version of foo or an error message).
+
+ 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 = ".";
+
+ if (try_cwd_first || string[0] == '/')
+ {
+ filename = string;
+ fd = open (filename, mode, prot);
+ if (fd >= 0 || string[0] == '/' || strchr (string, '/'))
+ goto done;
+ }
+
+ /* ./foo => foo */
+ while (string[0] == '.' && string[1] == '/')
+ string += 2;
+
+ alloclen = strlen (path) + strlen (string) + 2;
+ filename = (char *) alloca (alloclen);
+ fd = -1;
+ for (p = path; p; p = p1 ? p1 + 1 : 0)
+ {
+ p1 = (char *) strchr (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;
+ }
+
+ /* Remove trailing slashes */
+ while (len > 0 && 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, NULL);
+ }
+
+ return fd;
+}
+
+/* Open a source file given a symtab S. Returns a file descriptor
+ or negative number for error. */
+
+static int
+open_source_file (s)
+ struct symtab *s;
+{
+ char *path = source_path;
+ char *p;
+ int result;
+ char *fullname;
+
+ /* 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. */
+ mfree (s->objfile->md, s->fullname);
+ s->fullname = NULL;
+ }
+
+ if (s->dirname != NULL)
+ {
+ /* Replace a path entry of $cdir with the compilation directory name */
+#define cdir_len 5
+ /* We cast strstr's result in case an ANSIhole has made it const,
+ which produces a "required warning" when assigned to a nonconst. */
+ p = (char *)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 */
+ }
+ }
+
+ result = openp (path, 0, s->filename, O_RDONLY, 0, &s->fullname);
+ if (result < 0)
+ {
+ /* Didn't work. Try using just the basename. */
+ p = basename (s->filename);
+ if (p != s->filename)
+ result = openp(path, 0, p, O_RDONLY,0, &s->fullname);
+ }
+ if (result >= 0)
+ {
+ fullname = s -> fullname;
+ s -> fullname = mstrsave (s -> objfile -> md, s -> fullname);
+ free (fullname);
+ }
+ return result;
+}
+
+
+/* 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;
+ long exec_mtime;
+ int size;
+#ifdef LSEEK_NOT_LINEAR
+ char c;
+#endif
+
+ line_charpos = (int *) xmmalloc (s -> objfile -> md,
+ lines_allocated * sizeof (int));
+ if (fstat (desc, &st) < 0)
+ perror_with_name (s->filename);
+
+ if (exec_bfd) {
+ exec_mtime = bfd_get_mtime(exec_bfd);
+ if (exec_mtime && exec_mtime < st.st_mtime)
+ printf_filtered ("Source file is more recent than executable.\n");
+ }
+
+#ifdef LSEEK_NOT_LINEAR
+ /* Have to read it byte by byte to find out where the chars live */
+
+ line_charpos[0] = tell(desc);
+ nlines = 1;
+ while (myread(desc, &c, 1)>0)
+ {
+ if (c == '\n')
+ {
+ if (nlines == lines_allocated)
+ {
+ lines_allocated *= 2;
+ line_charpos =
+ (int *) xmrealloc (s -> objfile -> md, (char *) line_charpos,
+ sizeof (int) * lines_allocated);
+ }
+ line_charpos[nlines++] = tell(desc);
+ }
+ }
+
+#else
+ /* st_size might be a large type, but we only support source files whose
+ size fits in an int. FIXME. */
+ size = (int) st.st_size;
+
+#ifdef BROKEN_LARGE_ALLOCA
+ data = (char *) xmalloc (size);
+ make_cleanup (free, data);
+#else
+ data = (char *) alloca (size);
+#endif
+ if (myread (desc, data, size) < 0)
+ perror_with_name (s->filename);
+ end = data + 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 *) xmrealloc (s -> objfile -> md, (char *) line_charpos,
+ sizeof (int) * lines_allocated);
+ }
+ line_charpos[nlines++] = p - data;
+ }
+ }
+#endif
+ s->nlines = nlines;
+ s->line_charpos =
+ (int *) xmrealloc (s -> objfile -> md, (char *) line_charpos,
+ nlines * sizeof (int));
+
+}
+
+/* Return the character position of a line LINE in symtab S.
+ Return 0 if anything is invalid. */
+
+#if 0 /* Currently unused */
+
+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;
+}
+
+#endif /* 0 */
+
+
+/* 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. */
+
+static 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, pc)
+ struct symtab *s;
+ int line;
+ int mid_statement;
+ CORE_ADDR pc;
+{
+ if (s->line_charpos == 0)
+ get_filename_and_charpos (s, (char **)NULL);
+ if (s->fullname == 0)
+ return 0;
+ if (line > s->nlines)
+ /* Don't index off the end of the line_charpos array. */
+ return 0;
+ printf ("\032\032%s:%d:%d:%s:0x%lx\n", s->fullname,
+ line, s->line_charpos[line - 1],
+ mid_statement ? "middle" : "beg",
+ (unsigned long) pc);
+ current_source_line = line;
+ first_line_listed = line;
+ last_line_listed = line;
+ current_source_symtab = s;
+ return 1;
+}
+
+/* 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, FOPEN_RT);
+ 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' && c != '\r')
+ 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);
+}
+
+
+
+/*
+ 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_filtered("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 (!have_full_symbols () && !have_partial_symbols())
+ error ("No symbol table is loaded. Use the \"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 || STREQ (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 (STREQ (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, 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, 0);
+ else
+ sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0);
+ 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 %s.",
+ local_hex_string((unsigned long) sal.pc));
+ sym = find_pc_function (sal.pc);
+ if (sym)
+ {
+ printf_filtered ("%s is in ",
+ local_hex_string((unsigned long) sal.pc));
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), stdout);
+ printf_filtered (" (%s:%d).\n", sal.symtab->filename, sal.line);
+ }
+ else
+ printf_filtered ("%s is at %s:%d.\n",
+ local_hex_string((unsigned long) 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 + (lines_to_list / 2), 0);
+ else
+ print_source_lines (sal.symtab, sal.line,
+ (dummy_end
+ ? sal.line + lines_to_list
+ : sal_end.line + 1),
+ 0);
+}
+
+/* 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);
+
+ dont_repeat ();
+ }
+
+ /* 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)
+ {
+ printf_filtered ("No line number information available");
+ if (sal.pc != 0)
+ {
+ /* This is useful for "info line *0x7f34". If we can't tell the
+ user about a source line, at least let them have the symbolic
+ address. */
+ printf_filtered (" for address ");
+ wrap_here (" ");
+ print_address (sal.pc, stdout);
+ }
+ else
+ printf_filtered (".");
+ printf_filtered ("\n");
+ }
+ else if (sal.line > 0
+ && find_line_pc_range (sal.symtab, sal.line, &start_pc, &end_pc))
+ {
+ if (start_pc == end_pc)
+ {
+ printf_filtered ("Line %d of \"%s\"",
+ sal.line, sal.symtab->filename);
+ wrap_here (" ");
+ printf_filtered (" is at address ");
+ print_address (start_pc, stdout);
+ wrap_here (" ");
+ printf_filtered (" but contains no code.\n");
+ }
+ else
+ {
+ printf_filtered ("Line %d of \"%s\"",
+ sal.line, sal.symtab->filename);
+ wrap_here (" ");
+ printf_filtered (" starts at address ");
+ print_address (start_pc, stdout);
+ wrap_here (" ");
+ printf_filtered (" and ends at ");
+ print_address (end_pc, stdout);
+ printf_filtered (".\n");
+ }
+
+ /* 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;
+
+ /* If this is the only line, show the source code. If it could
+ not find the file, don't do anything special. */
+ if (frame_file_full_name && sals.nelts == 1)
+ identify_source_line (sal.symtab, sal.line, 0, start_pc);
+ }
+ else
+ /* Is there any case in which we get here, and have an address
+ which the user would want to see? If we have debugging symbols
+ and no line numbers? */
+ printf_filtered ("Line number %d is out of range for \"%s\".\n",
+ sal.line, sal.symtab->filename);
+ }
+ free (sals.sals);
+}
+
+/* Commands to search the source file for a regexp. */
+
+/* ARGSUSED */
+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, FOPEN_RT);
+ clearerr (stream);
+ while (1) {
+/* FIXME!!! We walk right off the end of buf if we get a long line!!! */
+ char buf[4096]; /* Should be reasonable??? */
+ register char *p = buf;
+
+ c = getc (stream);
+ if (c == EOF)
+ break;
+ do {
+ *p++ = c;
+ } while (c != '\n' && (c = getc (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_filtered ("Expression not found\n");
+ fclose (stream);
+}
+
+/* ARGSUSED */
+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, FOPEN_RT);
+ clearerr (stream);
+ while (line > 1)
+ {
+/* FIXME!!! We walk right off the end of buf if we get a long line!!! */
+ char buf[4096]; /* Should be reasonable??? */
+ register char *p = buf;
+
+ c = getc (stream);
+ if (c == EOF)
+ break;
+ do {
+ *p++ = c;
+ } while (c != '\n' && (c = getc (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_filtered ("Expression not found\n");
+ fclose (stream);
+ return;
+}
+
+void
+_initialize_source ()
+{
+ struct cmd_list_element *c;
+ current_source_symtab = 0;
+ init_source_path ();
+
+ /* The intention is to use POSIX Basic Regular Expressions.
+ Always use the GNU regex routine for consistency across all hosts.
+ Our current GNU regex.c does not have all the POSIX features, so this is
+ just an approximation. */
+ re_set_syntax (RE_SYNTAX_GREP);
+
+ c = add_cmd ("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.",
+ &cmdlist);
+ c->completer = filename_completer;
+
+ add_cmd ("directories", no_class, show_directories,
+ "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.",
+ &showlist);
+
+ 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, 1);
+
+ add_show_from_set
+ (add_set_cmd ("listsize", class_support, var_uinteger,
+ (char *)&lines_to_list,
+ "Set number of source lines gdb will list by default.",
+ &setlist),
+ &showlist);
+}
diff --git a/gnu/usr.bin/gdb/gdb/stabsread.c b/gnu/usr.bin/gdb/gdb/stabsread.c
new file mode 100644
index 000000000000..e81c314b6def
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/stabsread.c
@@ -0,0 +1,3770 @@
+/* Support routines for decoding "stabs" debugging information format.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Support routines for reading and decoding debugging information in
+ the "stabs" format. This format is used with many systems that use
+ the a.out object file format, as well as some systems that use
+ COFF or ELF where the stabs data is placed in a special section.
+ Avoid placing any object file format specific code in this file. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "aout/stab_gnu.h" /* We always use GNU stabs, not native */
+#include "buildsym.h"
+#include "complaints.h"
+#include "demangle.h"
+
+#include <ctype.h>
+
+/* Ask stabsread.h to define the vars it normally declares `extern'. */
+#define EXTERN /**/
+#include "stabsread.h" /* Our own declarations */
+#undef EXTERN
+
+/* The routines that read and process a complete stabs for a C struct or
+ C++ class pass lists of data member fields and lists of member function
+ fields in an instance of a field_info structure, as defined below.
+ This is part of some reorganization of low level C++ support and is
+ expected to eventually go away... (FIXME) */
+
+struct field_info
+{
+ struct nextfield
+ {
+ struct nextfield *next;
+ int visibility;
+ struct field field;
+ } *list;
+ struct next_fnfieldlist
+ {
+ struct next_fnfieldlist *next;
+ struct fn_fieldlist fn_fieldlist;
+ } *fnlist;
+};
+
+static struct type *
+dbx_alloc_type PARAMS ((int [2], struct objfile *));
+
+static long read_huge_number PARAMS ((char **, int, int *));
+
+static struct type *error_type PARAMS ((char **));
+
+static void
+patch_block_stabs PARAMS ((struct pending *, struct pending_stabs *,
+ struct objfile *));
+
+static void
+fix_common_block PARAMS ((struct symbol *, int));
+
+static int
+read_type_number PARAMS ((char **, int *));
+
+static struct type *
+read_range_type PARAMS ((char **, int [2], struct objfile *));
+
+static struct type *
+read_sun_builtin_type PARAMS ((char **, int [2], struct objfile *));
+
+static struct type *
+read_sun_floating_type PARAMS ((char **, int [2], struct objfile *));
+
+static struct type *
+read_enum_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type *
+rs6000_builtin_type PARAMS ((int));
+
+static int
+read_member_functions PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static int
+read_struct_fields PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static int
+read_baseclasses PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static int
+read_tilde_fields PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static int
+attach_fn_fields_to_type PARAMS ((struct field_info *, struct type *));
+
+static int
+attach_fields_to_type PARAMS ((struct field_info *, struct type *,
+ struct objfile *));
+
+static struct type *
+read_struct_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type *
+read_array_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type **
+read_args PARAMS ((char **, int, struct objfile *));
+
+static int
+read_cpp_abbrev PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static const char vptr_name[] = { '_','v','p','t','r',CPLUS_MARKER,'\0' };
+static const char vb_name[] = { '_','v','b',CPLUS_MARKER,'\0' };
+
+/* 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
+
+#if 0
+/* I think this can go away, all current uses have been removed.
+ GCC emits a few crazy types which can only be distinguished by the
+ name (complex, long long on some machines), but I'd say fix GCC. */
+
+/* During some calls to read_type (and thus to read_range_type), this
+ contains the name of the type being defined. Range types are only
+ used in C as basic types. We use the name to distinguish the otherwise
+ identical basic types "int" and "long" and their unsigned versions.
+ FIXME, this should disappear with better type management. */
+
+static char *long_kludge_name;
+#endif
+
+#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 invalid_cpp_abbrev_complaint =
+ {"invalid C++ abbreviation `%s'", 0, 0};
+
+struct complaint invalid_cpp_type_complaint =
+ {"C++ abbreviated type name unknown at symtab pos %d", 0, 0};
+
+struct complaint member_fn_complaint =
+ {"member function type missing, got '%c'", 0, 0};
+
+struct complaint const_vol_complaint =
+ {"const/volatile indicator missing, got '%c'", 0, 0};
+
+struct complaint error_type_complaint =
+ {"debug info mismatch between compiler and debugger", 0, 0};
+
+struct complaint invalid_member_complaint =
+ {"invalid (minimal) member type data format at symtab pos %d.", 0, 0};
+
+struct complaint range_type_base_complaint =
+ {"base type %d of range type is not defined", 0, 0};
+
+struct complaint reg_value_complaint =
+ {"register number too large in symbol %s", 0, 0};
+
+struct complaint vtbl_notfound_complaint =
+ {"virtual function table pointer not found when defining class `%s'", 0, 0};
+
+struct complaint unrecognized_cplus_name_complaint =
+ {"Unknown C++ symbol name `%s'", 0, 0};
+
+struct complaint rs6000_builtin_complaint =
+ {"Unknown builtin type %d", 0, 0};
+
+struct complaint stabs_general_complaint =
+ {"%s", 0, 0};
+
+/* Make a list of forward references which haven't been defined. */
+
+static struct type **undef_types;
+static int undef_types_allocated;
+static int undef_types_length;
+
+/* Check for and handle cretinous stabs symbol name continuation! */
+#define STABS_CONTINUE(pp) \
+ do { \
+ if (**(pp) == '\\') *(pp) = next_symbol_text (); \
+ } while (0)
+
+
+/* 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. */
+
+struct type **
+dbx_lookup_type (typenums)
+ int typenums[2];
+{
+ register int filenum = typenums[0];
+ register int index = typenums[1];
+ unsigned old_len;
+ register int real_filenum;
+ register struct header_file *f;
+ int f_orig_length;
+
+ if (filenum == -1) /* -1,-1 is for temporary types. */
+ return 0;
+
+ if (filenum < 0 || filenum >= n_this_object_header_files)
+ {
+ static struct complaint msg = {"\
+Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.",
+ 0, 0};
+ complain (&msg, filenum, index, symnum);
+ goto error_return;
+ }
+
+ if (filenum == 0)
+ {
+ if (index < 0)
+ {
+ /* Caller wants address of address of type. We think
+ that negative (rs6k builtin) types will never appear as
+ "lvalues", (nor should they), so we stuff the real type
+ pointer into a temp, and return its address. If referenced,
+ this will do the right thing. */
+ static struct type *temp_type;
+
+ temp_type = rs6000_builtin_type(index);
+ return &temp_type;
+ }
+
+ /* Type is defined outside of header files.
+ Find it in this object file's type vector. */
+ if (index >= type_vector_length)
+ {
+ old_len = type_vector_length;
+ if (old_len == 0)
+ {
+ type_vector_length = INITIAL_TYPE_VECTOR_LENGTH;
+ type_vector = (struct type **)
+ malloc (type_vector_length * sizeof (struct type *));
+ }
+ while (index >= type_vector_length)
+ {
+ type_vector_length *= 2;
+ }
+ type_vector = (struct type **)
+ xrealloc ((char *) type_vector,
+ (type_vector_length * sizeof (struct type *)));
+ memset (&type_vector[old_len], 0,
+ (type_vector_length - old_len) * sizeof (struct type *));
+ }
+ return (&type_vector[index]);
+ }
+ else
+ {
+ real_filenum = this_object_header_files[filenum];
+
+ if (real_filenum >= n_header_files)
+ {
+ struct type *temp_type;
+ struct type **temp_type_p;
+
+ warning ("GDB internal error: bad real_filenum");
+
+ error_return:
+ temp_type = init_type (TYPE_CODE_ERROR, 0, 0, NULL, NULL);
+ temp_type_p = (struct type **) xmalloc (sizeof (struct type *));
+ *temp_type_p = temp_type;
+ return temp_type_p;
+ }
+
+ 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 ((char *) f->vector, f->length * sizeof (struct type *));
+ memset (&f->vector[f_orig_length], 0,
+ (f->length - f_orig_length) * sizeof (struct type *));
+ }
+ return (&f->vector[index]);
+ }
+}
+
+/* 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, objfile)
+ int typenums[2];
+ struct objfile *objfile;
+{
+ register struct type **type_addr;
+
+ if (typenums[0] == -1)
+ {
+ return (alloc_type (objfile));
+ }
+
+ type_addr = dbx_lookup_type (typenums);
+
+ /* 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_addr == 0)
+ {
+ *type_addr = alloc_type (objfile);
+ }
+
+ return (*type_addr);
+}
+
+/* for all the stabs in a given stab vector, build appropriate types
+ and fix their symbols in given symbol vector. */
+
+static void
+patch_block_stabs (symbols, stabs, objfile)
+ struct pending *symbols;
+ struct pending_stabs *stabs;
+ struct objfile *objfile;
+{
+ int ii;
+ char *name;
+ char *pp;
+ struct symbol *sym;
+
+ if (stabs)
+ {
+
+ /* for all the stab entries, find their corresponding symbols and
+ patch their types! */
+
+ for (ii = 0; ii < stabs->count; ++ii)
+ {
+ name = stabs->stab[ii];
+ pp = (char*) strchr (name, ':');
+ sym = find_symbol_in_list (symbols, name, pp-name);
+ if (!sym)
+ {
+ /* On xcoff, if a global is defined and never referenced,
+ ld will remove it from the executable. There is then
+ a N_GSYM stab for it, but no regular (C_EXT) symbol. */
+ sym = (struct symbol *)
+ obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ SYMBOL_NAME (sym) =
+ obstack_copy0 (&objfile->symbol_obstack, name, pp - name);
+ pp += 2;
+ if (*(pp-1) == 'F' || *(pp-1) == 'f')
+ {
+ /* I don't think the linker does this with functions,
+ so as far as I know this is never executed.
+ But it doesn't hurt to check. */
+ SYMBOL_TYPE (sym) =
+ lookup_function_type (read_type (&pp, objfile));
+ }
+ else
+ {
+ SYMBOL_TYPE (sym) = read_type (&pp, objfile);
+ }
+ add_symbol_to_list (sym, &global_symbols);
+ }
+ else
+ {
+ pp += 2;
+ if (*(pp-1) == 'F' || *(pp-1) == 'f')
+ {
+ SYMBOL_TYPE (sym) =
+ lookup_function_type (read_type (&pp, objfile));
+ }
+ else
+ {
+ SYMBOL_TYPE (sym) = read_type (&pp, objfile);
+ }
+ }
+ }
+ }
+}
+
+
+/* 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.
+
+ Returns 0 for success, -1 for error. */
+
+static int
+read_type_number (pp, typenums)
+ register char **pp;
+ register int *typenums;
+{
+ int nbits;
+ if (**pp == '(')
+ {
+ (*pp)++;
+ typenums[0] = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0) return -1;
+ typenums[1] = read_huge_number (pp, ')', &nbits);
+ if (nbits != 0) return -1;
+ }
+ else
+ {
+ typenums[0] = 0;
+ typenums[1] = read_huge_number (pp, 0, &nbits);
+ if (nbits != 0) return -1;
+ }
+ return 0;
+}
+
+
+/* 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;
+
+/* ARGSUSED */
+struct symbol *
+define_symbol (valu, string, desc, type, objfile)
+ CORE_ADDR valu;
+ char *string;
+ int desc;
+ int type;
+ struct objfile *objfile;
+{
+ register struct symbol *sym;
+ char *p = (char *) strchr (string, ':');
+ int deftype;
+ int synonym = 0;
+ register int i;
+
+ /* We would like to eliminate nameless symbols, but keep their types.
+ E.g. stab entry ":t10=*2" should produce a type 10, which is a pointer
+ to type 2, but, should not create a symbol to address that type. Since
+ the symbol will be nameless, there is no way any user can refer to it. */
+
+ int nameless;
+
+ /* Ignore syms with empty names. */
+ if (string[0] == 0)
+ return 0;
+
+ /* Ignore old-style symbols from cc -go */
+ if (p == 0)
+ return 0;
+
+ /* If a nameless stab entry, all we need is the type, not the symbol.
+ e.g. ":t10=*2" or a nameless enum like " :T16=ered:0,green:1,blue:2,;" */
+ nameless = (p == string || ((string[0] == ' ') && (string[1] == ':')));
+
+ sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, 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) = obsavestring ("this", strlen ("this"),
+ &objfile -> symbol_obstack);
+ break;
+
+ case 'v': /* $vtbl_ptr_type */
+ /* Was: SYMBOL_NAME (sym) = "vptr"; */
+ goto normal;
+
+ case 'e':
+ SYMBOL_NAME (sym) = obsavestring ("eh_throw", strlen ("eh_throw"),
+ &objfile -> symbol_obstack);
+ break;
+
+ case '_':
+ /* This was an anonymous type that was never fixed up. */
+ goto normal;
+
+ default:
+ complain (&unrecognized_cplus_name_complaint, string);
+ goto normal; /* Do *something* with it */
+ }
+ }
+ else
+ {
+ normal:
+ SYMBOL_LANGUAGE (sym) = current_subfile -> language;
+ SYMBOL_NAME (sym) = (char *)
+ obstack_alloc (&objfile -> symbol_obstack, ((p - string) + 1));
+ /* Open-coded memcpy--saves function call time. */
+ /* FIXME: Does it really? Try replacing with simple strcpy and
+ try it on an executable with a large symbol table. */
+ /* FIXME: considering that gcc can open code memcpy anyway, I
+ doubt it. xoxorich. */
+ {
+ register char *p1 = string;
+ register char *p2 = SYMBOL_NAME (sym);
+ while (p1 != p)
+ {
+ *p2++ = *p1++;
+ }
+ *p2++ = '\0';
+ }
+
+ /* If this symbol is from a C++ compilation, then attempt to cache the
+ demangled form for future reference. This is a typical time versus
+ space tradeoff, that was decided in favor of time because it sped up
+ C++ symbol lookups by a factor of about 20. */
+
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+ }
+ p++;
+
+ /* Determine the type of name being defined. */
+#if 0
+ /* Getting GDB to correctly skip the symbol on an undefined symbol
+ descriptor and not ever dump core is a very dodgy proposition if
+ we do things this way. I say the acorn RISC machine can just
+ fix their compiler. */
+ /* 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. */
+ if (!strchr ("cfFGpPrStTvVXCR", *p))
+#else
+ if (isdigit (*p) || *p == '(' || *p == '-')
+#endif
+ deftype = 'l';
+ else
+ deftype = *p++;
+
+ switch (deftype)
+ {
+ case 'c':
+ /* c is a special case, not followed by a type-number.
+ SYMBOL:c=iVALUE for an integer constant symbol.
+ SYMBOL:c=rVALUE for a floating constant symbol.
+ SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ if (*p != '=')
+ {
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = error_type (&p);
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ return sym;
+ }
+ ++p;
+ switch (*p++)
+ {
+ case 'r':
+ {
+ double d = atof (p);
+ char *dbl_valu;
+
+ /* FIXME: lookup_fundamental_type is a hack. We should be
+ creating a type especially for the type of float constants.
+ Problem is, what type should it be? We currently have to
+ read this in host floating point format, but what type
+ represents a host format "double"?
+
+ Also, what should the name of this type be? Should we
+ be using 'S' constants (see stabs.texinfo) instead? */
+
+ SYMBOL_TYPE (sym) = lookup_fundamental_type (objfile,
+ FT_DBL_PREC_FLOAT);
+ dbl_valu = (char *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (double));
+ memcpy (dbl_valu, &d, sizeof (double));
+ /* Put it in target byte order, but it's still in host
+ floating point format. */
+ SWAP_TARGET_AND_HOST (dbl_valu, sizeof (double));
+ SYMBOL_VALUE_BYTES (sym) = dbl_valu;
+ SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+ }
+ break;
+ case 'i':
+ {
+ /* Defining integer constants this way is kind of silly,
+ since 'e' constants allows the compiler to give not
+ only the value, but the type as well. C has at least
+ int, long, unsigned int, and long long as constant
+ types; other languages probably should have at least
+ unsigned as well as signed constants. */
+
+ /* We just need one int constant type for all objfiles.
+ It doesn't depend on languages or anything (arguably its
+ name should be a language-specific name for a type of
+ that size, but I'm inclined to say that if the compiler
+ wants a nice name for the type, it can use 'e'). */
+ static struct type *int_const_type;
+
+ /* Yes, this is as long as a *host* int. That is because we
+ use atoi. */
+ if (int_const_type == NULL)
+ int_const_type =
+ init_type (TYPE_CODE_INT,
+ sizeof (int) * HOST_CHAR_BIT / TARGET_CHAR_BIT, 0,
+ "integer constant",
+ (struct objfile *)NULL);
+ SYMBOL_TYPE (sym) = int_const_type;
+ SYMBOL_VALUE (sym) = atoi (p);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ }
+ break;
+ case 'e':
+ /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
+ can be represented as integral.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ {
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+
+ if (*p != ',')
+ {
+ SYMBOL_TYPE (sym) = error_type (&p);
+ break;
+ }
+ ++p;
+
+ /* If the value is too big to fit in an int (perhaps because
+ it is unsigned), or something like that, we silently get
+ a bogus value. The type and everything else about it is
+ correct. Ideally, we should be using whatever we have
+ available for parsing unsigned and long long values,
+ however. */
+ SYMBOL_VALUE (sym) = atoi (p);
+ }
+ break;
+ default:
+ {
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = error_type (&p);
+ }
+ }
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ return sym;
+
+ case 'C':
+ /* The name of a caught exception. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ 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':
+ /* A static function definition. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ /* fall into process_function_types. */
+
+ process_function_types:
+ /* Function result types are described as the result type in stabs.
+ We need to convert this to the function-returning-type-X type
+ in GDB. E.g. "int" is converted to "function returning int". */
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_FUNC)
+ {
+#if 0
+ /* This code doesn't work -- it needs to realloc and can't. */
+ /* Attempt to set up to record a function prototype... */
+ struct type *new = alloc_type (objfile);
+
+ /* Generate a template for the type of this function. The
+ types of the arguments will be added as we read the symbol
+ table. */
+ *new = *lookup_function_type (SYMBOL_TYPE(sym));
+ SYMBOL_TYPE(sym) = new;
+ TYPE_OBJFILE (new) = objfile;
+ in_function_type = new;
+#else
+ SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+#endif
+ }
+ /* fall into process_prototype_types */
+
+ process_prototype_types:
+ /* Sun acc puts declared types of arguments here. We don't care
+ about their actual types (FIXME -- we should remember the whole
+ function prototype), but the list may define some new types
+ that we have to remember, so we must scan it now. */
+ while (*p == ';') {
+ p++;
+ read_type (&p, objfile);
+ }
+ break;
+
+ case 'F':
+ /* A global function definition. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &global_symbols);
+ goto process_function_types;
+
+ 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. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ 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_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'p':
+ if (*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, objfile)));
+ }
+ else
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+
+ /* 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;
+#if 0
+ /* This doesn't work yet. */
+ add_param_to_type (&in_function_type, sym);
+#endif
+ add_symbol_to_list (sym, &local_symbols);
+
+#if TARGET_BYTE_ORDER == LITTLE_ENDIAN
+ /* On little-endian machines, this crud is never necessary, and,
+ if the extra bytes contain garbage, is harmful. */
+ break;
+#else /* Big endian. */
+ /* If it's gcc-compiled, if it says `short', believe it. */
+ if (processing_gcc_compilation || BELIEVE_PCC_PROMOTION)
+ break;
+
+#if !BELIEVE_PCC_PROMOTION
+ {
+ /* This is the signed type which arguments get promoted to. */
+ static struct type *pcc_promotion_type;
+ /* This is the unsigned type which arguments get promoted to. */
+ static struct type *pcc_unsigned_promotion_type;
+
+ /* Call it "int" because this is mainly C lossage. */
+ if (pcc_promotion_type == NULL)
+ pcc_promotion_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "int", NULL);
+
+ if (pcc_unsigned_promotion_type == NULL)
+ pcc_unsigned_promotion_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned int", NULL);
+
+#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 the parameter is shorter than an int, and is integral
+ (e.g. char, short, or unsigned equivalent), and is claimed to
+ be passed on an integer boundary, don't believe it! Offset the
+ parameter's address to the tail-end of that integer. */
+
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (pcc_promotion_type)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT
+ && 0 == SYMBOL_VALUE (sym) % TYPE_LENGTH (pcc_promotion_type))
+ {
+ SYMBOL_VALUE (sym) += TYPE_LENGTH (pcc_promotion_type)
+ - TYPE_LENGTH (SYMBOL_TYPE (sym));
+ }
+ break;
+
+#else /* no BELIEVE_PCC_PROMOTION_TYPE. */
+
+ /* If PCC says a parameter is a short or a char,
+ it is really an int. */
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (pcc_promotion_type)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT)
+ {
+ SYMBOL_TYPE (sym) =
+ TYPE_UNSIGNED (SYMBOL_TYPE (sym))
+ ? pcc_unsigned_promotion_type
+ : pcc_promotion_type;
+ }
+ break;
+
+#endif /* no BELIEVE_PCC_PROMOTION_TYPE. */
+ }
+#endif /* !BELIEVE_PCC_PROMOTION. */
+#endif /* Big endian. */
+
+ case 'P':
+ /* acc seems to use P to delare the prototypes of functions that
+ are referenced by this file. gdb is not prepared to deal
+ with this extra information. FIXME, it ought to. */
+ if (type == N_FUN)
+ {
+ read_type (&p, objfile);
+ goto process_prototype_types;
+ }
+ /*FALLTHROUGH*/
+
+ case 'R':
+ /* Parameter which is in a register. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+ if (SYMBOL_VALUE (sym) >= NUM_REGS)
+ {
+ complain (&reg_value_complaint, SYMBOL_SOURCE_NAME (sym));
+ SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
+ }
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'r':
+ /* Register variable (either global or local). */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+ if (SYMBOL_VALUE (sym) >= NUM_REGS)
+ {
+ complain (&reg_value_complaint, SYMBOL_SOURCE_NAME (sym));
+ SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
+ }
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (within_function)
+ {
+ /* Sun cc uses a pair of symbols, one 'p' and one 'r' with the same
+ name to represent an argument passed in a register.
+ GCC uses 'P' for the same case. So if we find such a symbol pair
+ we combine it into one 'P' symbol.
+ Note that this code illegally combines
+ main(argc) int argc; { register int argc = 1; }
+ but this case is considered pathological and causes a warning
+ from a decent compiler. */
+ if (local_symbols
+ && local_symbols->nsyms > 0)
+ {
+ struct symbol *prev_sym;
+ prev_sym = local_symbols->symbol[local_symbols->nsyms - 1];
+ if (SYMBOL_CLASS (prev_sym) == LOC_ARG
+ && STREQ (SYMBOL_NAME (prev_sym), SYMBOL_NAME(sym)))
+ {
+ SYMBOL_CLASS (prev_sym) = LOC_REGPARM;
+ SYMBOL_VALUE (prev_sym) = SYMBOL_VALUE (sym);
+ sym = prev_sym;
+ break;
+ }
+ }
+ add_symbol_to_list (sym, &local_symbols);
+ }
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 'S':
+ /* Static symbol at top level of file */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ 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':
+#if 0
+ /* See comment where long_kludge_name is declared. */
+ /* Here we save the name of the symbol for read_range_type, which
+ ends up reading in the basic types. In stabs, unfortunately there
+ is no distinction between "int" and "long" types except their
+ names. Until we work out a saner type policy (eliminating most
+ builtin types and using the names specified in the files), we
+ save away the name so that far away from here in read_range_type,
+ we can examine it to decide between "int" and "long". FIXME. */
+ long_kludge_name = SYMBOL_NAME (sym);
+#endif
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+
+ /* For a nameless type, we don't want a create a symbol, thus we
+ did not use `sym'. Return without further processing. */
+ if (nameless) return NULL;
+
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ /* 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. */
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) != NULL)
+ if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
+ && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
+ {
+ int j;
+ for (j = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)) - 1; j >= 0; j--)
+ if (TYPE_BASECLASS_NAME (SYMBOL_TYPE (sym), j) == 0)
+ TYPE_BASECLASS_NAME (SYMBOL_TYPE (sym), j) =
+ type_name_no_tag (TYPE_BASECLASS (SYMBOL_TYPE (sym), j));
+ }
+
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == NULL)
+ {
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FUNC)
+ {
+ /* If we are giving a name to a type such as "pointer to
+ foo" or "function returning foo", we better not set
+ the TYPE_NAME. If the program contains "typedef char
+ *caddr_t;", we don't want all variables of type char
+ * to print as caddr_t. This is not just a
+ consequence of GDB's type management; PCC and GCC (at
+ least through version 2.4) both output variables of
+ either type char * or caddr_t with the type number
+ defined in the 't' symbol for caddr_t. If a future
+ compiler cleans this up it GDB is not ready for it
+ yet, but if it becomes ready we somehow need to
+ disable this check (without breaking the PCC/GCC2.4
+ case).
+
+ Sigh.
+
+ Fortunately, this check seems not to be necessary
+ for anything except pointers or functions. */
+ }
+ else
+ TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_NAME (sym);
+ }
+
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 'T':
+ /* Struct, union, or enum tag. For GNU C++, this can be be followed
+ by 't' which means we are typedef'ing it as well. */
+ synonym = *p == 't';
+
+ if (synonym)
+ {
+ p++;
+ type_synonym_name = obsavestring (SYMBOL_NAME (sym),
+ strlen (SYMBOL_NAME (sym)),
+ &objfile -> symbol_obstack);
+ }
+
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+
+ /* For a nameless type, we don't want a create a symbol, thus we
+ did not use `sym'. Return without further processing. */
+ if (nameless) return NULL;
+
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0)
+ TYPE_TAG_NAME (SYMBOL_TYPE (sym))
+ = obconcat (&objfile -> type_obstack, "", "", SYMBOL_NAME (sym));
+ add_symbol_to_list (sym, &file_symbols);
+
+ if (synonym)
+ {
+ /* Clone the sym and then modify it. */
+ register struct symbol *typedef_sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ *typedef_sym = *sym;
+ SYMBOL_CLASS (typedef_sym) = LOC_TYPEDEF;
+ SYMBOL_VALUE (typedef_sym) = valu;
+ SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+ TYPE_NAME (SYMBOL_TYPE (sym))
+ = obconcat (&objfile -> type_obstack, "", "", SYMBOL_NAME (sym));
+ add_symbol_to_list (typedef_sym, &file_symbols);
+ }
+ break;
+
+ case 'V':
+ /* Static symbol of local scope */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ 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_TYPE (sym) = read_type (&p, objfile);
+ 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_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ default:
+ SYMBOL_TYPE (sym) = error_type (&p);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ }
+
+ /* When passing structures to a function, some systems sometimes pass
+ the address in a register, not the structure itself.
+
+ If REG_STRUCT_HAS_ADDR yields non-zero we have to convert LOC_REGPARM
+ to LOC_REGPARM_ADDR for structures and unions. */
+
+#if !defined (REG_STRUCT_HAS_ADDR)
+#define REG_STRUCT_HAS_ADDR(gcc_p) 0
+#endif
+
+ if (SYMBOL_CLASS (sym) == LOC_REGPARM
+ && REG_STRUCT_HAS_ADDR (processing_gcc_compilation)
+ && ( (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT)
+ || (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)))
+ SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
+
+ return sym;
+}
+
+
+/* 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);
+ 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);
+}
+
+
+/* Read type information or a type definition; return the type. Even
+ though this routine accepts either type information or a type
+ definition, the distinction is relevant--some parts of stabsread.c
+ assume that type information starts with a digit, '-', or '(' in
+ deciding whether to call read_type. */
+
+struct type *
+read_type (pp, objfile)
+ register char **pp;
+ struct objfile *objfile;
+{
+ register struct type *type = 0;
+ struct type *type1;
+ int typenums[2];
+ int xtypenums[2];
+ char type_descriptor;
+
+ /* Size in bits of type if specified by a type attribute, or -1 if
+ there is no size attribute. */
+ int type_size = -1;
+
+ /* 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 == '('
+ || **pp == '-')
+ {
+ if (read_type_number (pp, typenums) != 0)
+ return error_type (pp);
+
+ /* Type is not being defined here. Either it already exists,
+ or this is a forward reference to it. dbx_alloc_type handles
+ both cases. */
+ if (**pp != '=')
+ return dbx_alloc_type (typenums, objfile);
+
+ /* Type is being defined here. */
+ /* Skip the '='. */
+ ++(*pp);
+
+ while (**pp == '@')
+ {
+ char *p = *pp + 1;
+ /* It might be a type attribute or a member type. */
+ if (isdigit (*p) || *p == '(' || *p == '-')
+ /* Member type. */
+ break;
+ else
+ {
+ /* Type attributes. */
+ char *attr = p;
+
+ /* Skip to the semicolon. */
+ while (*p != ';' && *p != '\0')
+ ++p;
+ *pp = p;
+ if (*p == '\0')
+ return error_type (pp);
+ else
+ /* Skip the semicolon. */
+ ++*pp;
+
+ switch (*attr)
+ {
+ case 's':
+ type_size = atoi (attr + 1);
+ if (type_size <= 0)
+ type_size = -1;
+ break;
+ default:
+ /* Ignore unrecognized type attributes, so future compilers
+ can invent new ones. */
+ break;
+ }
+ }
+ }
+ /* Skip the type descriptor, we get it below with (*pp)[-1]. */
+ ++(*pp);
+ }
+ 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)++;
+ }
+
+ type_descriptor = (*pp)[-1];
+ switch (type_descriptor)
+ {
+ case 'x':
+ {
+ enum type_code code;
+
+ /* Used to index through file_symbols. */
+ struct pending *ppt;
+ int i;
+
+ /* Name including "struct", etc. */
+ char *type_name;
+
+ {
+ char *from, *to;
+
+ /* Set the type code according to the following letter. */
+ switch ((*pp)[0])
+ {
+ case 's':
+ code = TYPE_CODE_STRUCT;
+ break;
+ case 'u':
+ code = TYPE_CODE_UNION;
+ break;
+ case 'e':
+ code = TYPE_CODE_ENUM;
+ break;
+ default:
+ return error_type (pp);
+ }
+
+ to = type_name = (char *)
+ obstack_alloc (&objfile -> type_obstack,
+ (((char *) strchr (*pp, ':') - (*pp)) + 1));
+
+ /* Copy the name. */
+ from = *pp + 1;
+ while ((*to++ = *from++) != ':')
+ ;
+ *--to = '\0';
+
+ /* Set the pointer ahead of the name which we just read. */
+ *pp = from;
+ }
+
+ /* 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)
+ && STREQ (SYMBOL_NAME (sym), type_name))
+ {
+ obstack_free (&objfile -> type_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, objfile);
+ TYPE_CODE (type) = code;
+ TYPE_TAG_NAME (type) = type_name;
+ INIT_CPLUS_SPECIFIC(type);
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+
+ add_undefined_type (type);
+ return type;
+ }
+
+ case '-': /* RS/6000 built-in type */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '(':
+
+ (*pp)--;
+ if (read_type_number (pp, xtypenums) != 0)
+ return error_type (pp);
+
+ if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
+ /* It's being defined as itself. That means it is "void". */
+ type = init_type (TYPE_CODE_VOID, 0, 0, NULL, objfile);
+ else
+ {
+ struct type *xtype = *dbx_lookup_type (xtypenums);
+
+ /* This can happen if we had '-' followed by a garbage character,
+ for example. */
+ if (xtype == NULL)
+ return error_type (pp);
+
+ /* The type is being defined to another type. So we copy the type.
+ This loses if we copy a C++ class and so we lose track of how
+ the names are mangled (but g++ doesn't output stabs like this
+ now anyway). */
+
+ type = alloc_type (objfile);
+ memcpy (type, xtype, sizeof (struct type));
+
+ /* The idea behind clearing the names is that the only purpose
+ for defining a type to another type is so that the name of
+ one can be different. So we probably don't need to worry much
+ about the case where the compiler doesn't give a name to the
+ new type. */
+ TYPE_NAME (type) = NULL;
+ TYPE_TAG_NAME (type) = NULL;
+ }
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ /* In the following types, we must be sure to overwrite any existing
+ type that the typenums refer to, rather than allocating a new one
+ and making the typenums point to the new one. This is because there
+ may already be pointers to the existing type (if it had been
+ forward-referenced), and we must change it to a pointer, function,
+ reference, or whatever, *in-place*. */
+
+ case '*':
+ type1 = read_type (pp, objfile);
+ type = make_pointer_type (type1, dbx_lookup_type (typenums));
+ break;
+
+ case '&': /* Reference to another type */
+ type1 = read_type (pp, objfile);
+ type = make_reference_type (type1, dbx_lookup_type (typenums));
+ break;
+
+ case 'f': /* Function returning another type */
+ type1 = read_type (pp, objfile);
+ type = make_function_type (type1, dbx_lookup_type (typenums));
+ break;
+
+ case 'k': /* Const qualifier on some type (Sun) */
+ type = read_type (pp, objfile);
+ /* FIXME! For now, we ignore const and volatile qualifiers. */
+ break;
+
+ case 'B': /* Volatile qual on some type (Sun) */
+ type = read_type (pp, objfile);
+ /* FIXME! For now, we ignore const and volatile qualifiers. */
+ break;
+
+/* FIXME -- we should be doing smash_to_XXX types here. */
+ case '@': /* Member (class & variable) type */
+ {
+ struct type *domain = read_type (pp, objfile);
+ struct type *memtype;
+
+ if (**pp != ',')
+ /* Invalid member type data format. */
+ return error_type (pp);
+ ++*pp;
+
+ memtype = read_type (pp, objfile);
+ type = dbx_alloc_type (typenums, objfile);
+ smash_to_member_type (type, domain, memtype);
+ }
+ break;
+
+ case '#': /* Method (class & fn) type */
+ if ((*pp)[0] == '#')
+ {
+ /* We'll get the parameter types from the name. */
+ struct type *return_type;
+
+ (*pp)++;
+ return_type = read_type (pp, objfile);
+ if (*(*pp)++ != ';')
+ complain (&invalid_member_complaint, symnum);
+ type = allocate_stub_method (return_type);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ }
+ else
+ {
+ struct type *domain = read_type (pp, objfile);
+ struct type *return_type;
+ struct type **args;
+
+ if (**pp != ',')
+ /* Invalid member type data format. */
+ return error_type (pp);
+ else
+ ++(*pp);
+
+ return_type = read_type (pp, objfile);
+ args = read_args (pp, ';', objfile);
+ type = dbx_alloc_type (typenums, objfile);
+ smash_to_method_type (type, domain, return_type, args);
+ }
+ break;
+
+ case 'r': /* Range type */
+ type = read_range_type (pp, typenums, objfile);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case 'b': /* Sun ACC builtin int type */
+ type = read_sun_builtin_type (pp, typenums, objfile);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case 'R': /* Sun ACC builtin float type */
+ type = read_sun_floating_type (pp, typenums, objfile);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case 'e': /* Enumeration type */
+ type = dbx_alloc_type (typenums, objfile);
+ type = read_enum_type (pp, type, objfile);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case 's': /* Struct type */
+ case 'u': /* Union type */
+ type = dbx_alloc_type (typenums, objfile);
+ if (!TYPE_NAME (type))
+ {
+ TYPE_NAME (type) = type_synonym_name;
+ }
+ type_synonym_name = NULL;
+ switch (type_descriptor)
+ {
+ case 's':
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ break;
+ case 'u':
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ break;
+ }
+ type = read_struct_type (pp, type, objfile);
+ break;
+
+ case 'a': /* Array type */
+ if (**pp != 'r')
+ return error_type (pp);
+ ++*pp;
+
+ type = dbx_alloc_type (typenums, objfile);
+ type = read_array_type (pp, type, objfile);
+ break;
+
+ default:
+ --*pp; /* Go back to the symbol in error */
+ /* Particularly important if it was \0! */
+ return error_type (pp);
+ }
+
+ if (type == 0)
+ {
+ warning ("GDB internal error, type is NULL in stabsread.c\n");
+ return error_type (pp);
+ }
+
+ /* Size specified in a type attribute overrides any other size. */
+ if (type_size != -1)
+ TYPE_LENGTH (type) = type_size / TARGET_CHAR_BIT;
+
+ return type;
+}
+
+/* RS/6000 xlc/dbx combination uses a set of builtin types, starting from -1.
+ Return the proper type node for a given builtin type number. */
+
+static struct type *
+rs6000_builtin_type (typenum)
+ int typenum;
+{
+ /* We recognize types numbered from -NUMBER_RECOGNIZED to -1. */
+#define NUMBER_RECOGNIZED 30
+ /* This includes an empty slot for type number -0. */
+ static struct type *negative_types[NUMBER_RECOGNIZED + 1];
+ struct type *rettype = NULL;
+
+ if (typenum >= 0 || typenum < -NUMBER_RECOGNIZED)
+ {
+ complain (&rs6000_builtin_complaint, typenum);
+ return builtin_type_error;
+ }
+ if (negative_types[-typenum] != NULL)
+ return negative_types[-typenum];
+
+#if TARGET_CHAR_BIT != 8
+ #error This code wrong for TARGET_CHAR_BIT not 8
+ /* These definitions all assume that TARGET_CHAR_BIT is 8. I think
+ that if that ever becomes not true, the correct fix will be to
+ make the size in the struct type to be in bits, not in units of
+ TARGET_CHAR_BIT. */
+#endif
+
+ switch (-typenum)
+ {
+ case 1:
+ /* The size of this and all the other types are fixed, defined
+ by the debugging format. If there is a type called "int" which
+ is other than 32 bits, then it should use a new negative type
+ number (or avoid negative type numbers for that case).
+ See stabs.texinfo. */
+ rettype = init_type (TYPE_CODE_INT, 4, 0, "int", NULL);
+ break;
+ case 2:
+ rettype = init_type (TYPE_CODE_INT, 1, 0, "char", NULL);
+ break;
+ case 3:
+ rettype = init_type (TYPE_CODE_INT, 2, 0, "short", NULL);
+ break;
+ case 4:
+ rettype = init_type (TYPE_CODE_INT, 4, 0, "long", NULL);
+ break;
+ case 5:
+ rettype = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED,
+ "unsigned char", NULL);
+ break;
+ case 6:
+ rettype = init_type (TYPE_CODE_INT, 1, 0, "signed char", NULL);
+ break;
+ case 7:
+ rettype = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED,
+ "unsigned short", NULL);
+ break;
+ case 8:
+ rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
+ "unsigned int", NULL);
+ break;
+ case 9:
+ rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
+ "unsigned", NULL);
+ case 10:
+ rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
+ "unsigned long", NULL);
+ break;
+ case 11:
+ rettype = init_type (TYPE_CODE_VOID, 0, 0, "void", NULL);
+ break;
+ case 12:
+ /* IEEE single precision (32 bit). */
+ rettype = init_type (TYPE_CODE_FLT, 4, 0, "float", NULL);
+ break;
+ case 13:
+ /* IEEE double precision (64 bit). */
+ rettype = init_type (TYPE_CODE_FLT, 8, 0, "double", NULL);
+ break;
+ case 14:
+ /* This is an IEEE double on the RS/6000, and different machines with
+ different sizes for "long double" should use different negative
+ type numbers. See stabs.texinfo. */
+ rettype = init_type (TYPE_CODE_FLT, 8, 0, "long double", NULL);
+ break;
+ case 15:
+ rettype = init_type (TYPE_CODE_INT, 4, 0, "integer", NULL);
+ break;
+ case 16:
+ rettype = init_type (TYPE_CODE_BOOL, 4, 0, "boolean", NULL);
+ break;
+ case 17:
+ rettype = init_type (TYPE_CODE_FLT, 4, 0, "short real", NULL);
+ break;
+ case 18:
+ rettype = init_type (TYPE_CODE_FLT, 8, 0, "real", NULL);
+ break;
+ case 19:
+ rettype = init_type (TYPE_CODE_ERROR, 0, 0, "stringptr", NULL);
+ break;
+ case 20:
+ rettype = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED,
+ "character", NULL);
+ break;
+ case 21:
+ rettype = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED,
+ "logical*1", NULL);
+ break;
+ case 22:
+ rettype = init_type (TYPE_CODE_BOOL, 2, TYPE_FLAG_UNSIGNED,
+ "logical*2", NULL);
+ break;
+ case 23:
+ rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
+ "logical*4", NULL);
+ break;
+ case 24:
+ rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
+ "logical", NULL);
+ break;
+ case 25:
+ /* Complex type consisting of two IEEE single precision values. */
+ rettype = init_type (TYPE_CODE_ERROR, 8, 0, "complex", NULL);
+ break;
+ case 26:
+ /* Complex type consisting of two IEEE double precision values. */
+ rettype = init_type (TYPE_CODE_ERROR, 16, 0, "double complex", NULL);
+ break;
+ case 27:
+ rettype = init_type (TYPE_CODE_INT, 1, 0, "integer*1", NULL);
+ break;
+ case 28:
+ rettype = init_type (TYPE_CODE_INT, 2, 0, "integer*2", NULL);
+ break;
+ case 29:
+ rettype = init_type (TYPE_CODE_INT, 4, 0, "integer*4", NULL);
+ break;
+ case 30:
+ rettype = init_type (TYPE_CODE_CHAR, 2, 0, "wchar", NULL);
+ break;
+ }
+ negative_types[-typenum] = rettype;
+ return rettype;
+}
+
+/* This page contains subroutines of read_type. */
+
+#define VISIBILITY_PRIVATE '0' /* Stabs character for private field */
+#define VISIBILITY_PROTECTED '1' /* Stabs character for protected fld */
+#define VISIBILITY_PUBLIC '2' /* Stabs character for public field */
+
+/* Read member function stabs info for C++ classes. The form of each member
+ function data is:
+
+ NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ;
+
+ An example with two member functions is:
+
+ afunc1::20=##15;:i;2A.;afunc2::20:i;2A.;
+
+ For the case of overloaded operators, the format is op$::*.funcs, where
+ $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
+ name (such as `+=') and `.' marks the end of the operator name.
+
+ Returns 1 for success, 0 for failure. */
+
+static int
+read_member_functions (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ int nfn_fields = 0;
+ int length = 0;
+ /* Total number of member functions defined in this class. If the class
+ defines two `f' functions, and one `g' function, then this will have
+ the value 3. */
+ int total_length = 0;
+ int i;
+ struct next_fnfield
+ {
+ struct next_fnfield *next;
+ struct fn_field fn_field;
+ } *sublist;
+ struct type *look_ahead_type;
+ struct next_fnfieldlist *new_fnlist;
+ struct next_fnfield *new_sublist;
+ char *main_fn_name;
+ register char *p;
+
+ /* Process each list until we find something that is not a member function
+ or find the end of the functions. */
+
+ while (**pp != ';')
+ {
+ /* We should be positioned at the start of the function name.
+ Scan forward to find the first ':' and if it is not the
+ first of a "::" delimiter, then this is not a member function. */
+ p = *pp;
+ while (*p != ':')
+ {
+ p++;
+ }
+ if (p[1] != ':')
+ {
+ break;
+ }
+
+ sublist = NULL;
+ look_ahead_type = NULL;
+ length = 0;
+
+ new_fnlist = (struct next_fnfieldlist *)
+ xmalloc (sizeof (struct next_fnfieldlist));
+ make_cleanup (free, new_fnlist);
+ memset (new_fnlist, 0, sizeof (struct next_fnfieldlist));
+
+ if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == CPLUS_MARKER)
+ {
+ /* This is a completely wierd case. In order to stuff in the
+ names that might contain colons (the usual name delimiter),
+ Mike Tiemann defined a different name format which is
+ signalled if the identifier is "op$". In that case, the
+ format is "op$::XXXX." where XXXX is the name. This is
+ used for names like "+" or "=". YUUUUUUUK! FIXME! */
+ /* 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] = {'o', 'p', CPLUS_MARKER};
+ char *o = opname + 3;
+
+ /* Skip past '::'. */
+ *pp = p + 2;
+
+ STABS_CONTINUE (pp);
+ p = *pp;
+ while (*p != '.')
+ {
+ *o++ = *p++;
+ }
+ main_fn_name = savestring (opname, o - opname);
+ /* Skip past '.' */
+ *pp = p + 1;
+ }
+ else
+ {
+ main_fn_name = savestring (*pp, p - *pp);
+ /* Skip past '::'. */
+ *pp = p + 2;
+ }
+ new_fnlist -> fn_fieldlist.name = main_fn_name;
+
+ do
+ {
+ new_sublist =
+ (struct next_fnfield *) xmalloc (sizeof (struct next_fnfield));
+ make_cleanup (free, new_sublist);
+ memset (new_sublist, 0, sizeof (struct next_fnfield));
+
+ /* Check for and handle cretinous dbx symbol name continuation! */
+ if (look_ahead_type == NULL)
+ {
+ /* Normal case. */
+ STABS_CONTINUE (pp);
+
+ new_sublist -> fn_field.type = read_type (pp, objfile);
+ if (**pp != ':')
+ {
+ /* Invalid symtab info for member function. */
+ return 0;
+ }
+ }
+ else
+ {
+ /* g++ version 1 kludge */
+ new_sublist -> fn_field.type = look_ahead_type;
+ look_ahead_type = NULL;
+ }
+
+ (*pp)++;
+ p = *pp;
+ while (*p != ';')
+ {
+ p++;
+ }
+
+ /* If this is just a stub, then we don't have the real name here. */
+
+ if (TYPE_FLAGS (new_sublist -> fn_field.type) & TYPE_FLAG_STUB)
+ {
+ if (!TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type))
+ TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type) = type;
+ new_sublist -> fn_field.is_stub = 1;
+ }
+ new_sublist -> fn_field.physname = savestring (*pp, p - *pp);
+ *pp = p + 1;
+
+ /* Set this member function's visibility fields. */
+ switch (*(*pp)++)
+ {
+ case VISIBILITY_PRIVATE:
+ new_sublist -> fn_field.is_private = 1;
+ break;
+ case VISIBILITY_PROTECTED:
+ new_sublist -> fn_field.is_protected = 1;
+ break;
+ }
+
+ STABS_CONTINUE (pp);
+ switch (**pp)
+ {
+ case 'A': /* Normal functions. */
+ new_sublist -> fn_field.is_const = 0;
+ new_sublist -> fn_field.is_volatile = 0;
+ (*pp)++;
+ break;
+ case 'B': /* `const' member functions. */
+ new_sublist -> fn_field.is_const = 1;
+ new_sublist -> fn_field.is_volatile = 0;
+ (*pp)++;
+ break;
+ case 'C': /* `volatile' member function. */
+ new_sublist -> fn_field.is_const = 0;
+ new_sublist -> fn_field.is_volatile = 1;
+ (*pp)++;
+ break;
+ case 'D': /* `const volatile' member function. */
+ new_sublist -> fn_field.is_const = 1;
+ new_sublist -> fn_field.is_volatile = 1;
+ (*pp)++;
+ break;
+ case '*': /* File compiled with g++ version 1 -- no info */
+ case '?':
+ case '.':
+ break;
+ default:
+ complain (&const_vol_complaint, **pp);
+ break;
+ }
+
+ switch (*(*pp)++)
+ {
+ case '*':
+ {
+ int nbits;
+ /* 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_huge_number (pp, ';', &nbits)) + 2;
+ if (nbits != 0)
+ return 0;
+
+ STABS_CONTINUE (pp);
+ if (**pp == ';' || **pp == '\0')
+ {
+ /* Must be g++ version 1. */
+ new_sublist -> fn_field.fcontext = 0;
+ }
+ else
+ {
+ /* Figure out from whence this virtual function came.
+ It may belong to virtual function table of
+ one of its baseclasses. */
+ look_ahead_type = read_type (pp, objfile);
+ if (**pp == ':')
+ {
+ /* g++ version 1 overloaded methods. */
+ }
+ else
+ {
+ new_sublist -> fn_field.fcontext = look_ahead_type;
+ if (**pp != ';')
+ {
+ return 0;
+ }
+ else
+ {
+ ++*pp;
+ }
+ look_ahead_type = NULL;
+ }
+ }
+ break;
+ }
+ case '?':
+ /* static member function. */
+ new_sublist -> fn_field.voffset = VOFFSET_STATIC;
+ if (strncmp (new_sublist -> fn_field.physname,
+ main_fn_name, strlen (main_fn_name)))
+ {
+ new_sublist -> fn_field.is_stub = 1;
+ }
+ break;
+
+ default:
+ /* error */
+ complain (&member_fn_complaint, (*pp)[-1]);
+ /* Fall through into normal member function. */
+
+ case '.':
+ /* normal member function. */
+ new_sublist -> fn_field.voffset = 0;
+ new_sublist -> fn_field.fcontext = 0;
+ break;
+ }
+
+ new_sublist -> next = sublist;
+ sublist = new_sublist;
+ length++;
+ STABS_CONTINUE (pp);
+ }
+ while (**pp != ';' && **pp != '\0');
+
+ (*pp)++;
+
+ new_fnlist -> fn_fieldlist.fn_fields = (struct fn_field *)
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct fn_field) * length);
+ memset (new_fnlist -> fn_fieldlist.fn_fields, 0,
+ sizeof (struct fn_field) * length);
+ for (i = length; (i--, sublist); sublist = sublist -> next)
+ {
+ new_fnlist -> fn_fieldlist.fn_fields[i] = sublist -> fn_field;
+ }
+
+ new_fnlist -> fn_fieldlist.length = length;
+ new_fnlist -> next = fip -> fnlist;
+ fip -> fnlist = new_fnlist;
+ nfn_fields++;
+ total_length += length;
+ STABS_CONTINUE (pp);
+ }
+
+ if (nfn_fields)
+ {
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
+ TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * nfn_fields);
+ memset (TYPE_FN_FIELDLISTS (type), 0,
+ sizeof (struct fn_fieldlist) * nfn_fields);
+ TYPE_NFN_FIELDS (type) = nfn_fields;
+ TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+ }
+
+ return 1;
+}
+
+/* Special GNU C++ name.
+
+ Returns 1 for success, 0 for failure. "failure" means that we can't
+ keep parsing and it's time for error_type(). */
+
+static int
+read_cpp_abbrev (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ register char *p;
+ char *name;
+ char cpp_abbrev;
+ struct type *context;
+
+ p = *pp;
+ if (*++p == 'v')
+ {
+ name = NULL;
+ cpp_abbrev = *++p;
+
+ *pp = p + 1;
+
+ /* At this point, *pp points to something like "22:23=*22...",
+ where the type number before the ':' is the "context" and
+ everything after is a regular type definition. Lookup the
+ type, find it's name, and construct the field name. */
+
+ context = read_type (pp, objfile);
+
+ switch (cpp_abbrev)
+ {
+ case 'f': /* $vf -- a virtual function table pointer */
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack, vptr_name, "", "");
+ break;
+
+ case 'b': /* $vb -- a virtual bsomethingorother */
+ name = type_name_no_tag (context);
+ if (name == NULL)
+ {
+ complain (&invalid_cpp_type_complaint, symnum);
+ name = "FOO";
+ }
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack, vb_name, name, "");
+ break;
+
+ default:
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack,
+ "INVALID_CPLUSPLUS_ABBREV", "", "");
+ break;
+ }
+
+ /* At this point, *pp points to the ':'. Skip it and read the
+ field type. */
+
+ p = ++(*pp);
+ if (p[-1] != ':')
+ {
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ return 0;
+ }
+ fip->list->field.type = read_type (pp, objfile);
+ if (**pp == ',')
+ (*pp)++; /* Skip the comma. */
+ else
+ return 0;
+
+ {
+ int nbits;
+ fip->list->field.bitpos = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return 0;
+ }
+ /* This field is unpacked. */
+ fip->list->field.bitsize = 0;
+ fip->list->visibility = VISIBILITY_PRIVATE;
+ }
+ else
+ {
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ /* We have no idea what syntax an unrecognized abbrev would have, so
+ better return 0. If we returned 1, we would need to at least advance
+ *pp to avoid an infinite loop. */
+ return 0;
+ }
+ return 1;
+}
+
+static void
+read_one_struct_field (fip, pp, p, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ char *p;
+ struct type *type;
+ struct objfile *objfile;
+{
+ fip -> list -> field.name =
+ obsavestring (*pp, p - *pp, &objfile -> type_obstack);
+ *pp = p + 1;
+
+ /* This means we have a visibility for a field coming. */
+ if (**pp == '/')
+ {
+ (*pp)++;
+ fip -> list -> visibility = *(*pp)++;
+ switch (fip -> list -> visibility)
+ {
+ case VISIBILITY_PRIVATE:
+ case VISIBILITY_PROTECTED:
+ break;
+
+ case VISIBILITY_PUBLIC:
+ /* Nothing to do */
+ break;
+
+ default:
+ /* Unknown visibility specifier. */
+ complain (&stabs_general_complaint,
+ "unknown visibility specifier");
+ return;
+ break;
+ }
+ }
+ else
+ {
+ /* normal dbx-style format, no explicit visibility */
+ fip -> list -> visibility = VISIBILITY_PUBLIC;
+ }
+
+ fip -> list -> field.type = read_type (pp, objfile);
+ if (**pp == ':')
+ {
+ p = ++(*pp);
+#if 0
+ /* Possible future hook for nested types. */
+ if (**pp == '!')
+ {
+ fip -> list -> field.bitpos = (long)-2; /* nested type */
+ p = ++(*pp);
+ }
+ else
+#endif
+ {
+ /* Static class member. */
+ fip -> list -> field.bitpos = (long) -1;
+ }
+ while (*p != ';')
+ {
+ p++;
+ }
+ fip -> list -> field.bitsize = (long) savestring (*pp, p - *pp);
+ *pp = p + 1;
+ return;
+ }
+ else if (**pp != ',')
+ {
+ /* Bad structure-type format. */
+ complain (&stabs_general_complaint, "bad structure-type format");
+ return;
+ }
+
+ (*pp)++; /* Skip the comma. */
+
+ {
+ int nbits;
+ fip -> list -> field.bitpos = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ {
+ complain (&stabs_general_complaint, "bad structure-type format");
+ return;
+ }
+ fip -> list -> field.bitsize = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ {
+ complain (&stabs_general_complaint, "bad structure-type format");
+ return;
+ }
+ }
+#if 0
+ /* FIXME-tiemann: Can't the compiler put out something which
+ lets us distinguish these? (or maybe just not put out anything
+ for the field). 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 (fip -> list -> field.bitpos == 0 && fip -> list -> field.bitsize == 0)
+ {
+ complain (&dbx_class_complaint);
+ /* Ignore this field. */
+ fip -> list = fip -> 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 (fip -> list -> field.type) != TYPE_CODE_INT
+ && TYPE_CODE (fip -> list -> field.type) != TYPE_CODE_ENUM)
+ {
+ fip -> list -> field.bitsize = 0;
+ }
+ if ((fip -> list -> field.bitsize
+ == TARGET_CHAR_BIT * TYPE_LENGTH (fip -> list -> field.type)
+ || (TYPE_CODE (fip -> list -> field.type) == TYPE_CODE_ENUM
+ && (fip -> list -> field.bitsize
+ == TARGET_INT_BIT)
+ )
+ )
+ &&
+ fip -> list -> field.bitpos % 8 == 0)
+ {
+ fip -> list -> field.bitsize = 0;
+ }
+ }
+}
+
+
+/* Read struct or class data fields. They have the form:
+
+ NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
+
+ At the end, we see a semicolon instead of a field.
+
+ In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
+ a static field.
+
+ The optional VISIBILITY is one of:
+
+ '/0' (VISIBILITY_PRIVATE)
+ '/1' (VISIBILITY_PROTECTED)
+ '/2' (VISIBILITY_PUBLIC)
+
+ or nothing, for C style fields with public visibility.
+
+ Returns 1 for success, 0 for failure. */
+
+static int
+read_struct_fields (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ register char *p;
+ struct nextfield *new;
+
+ /* We better set p right now, in case there are no fields at all... */
+
+ p = *pp;
+
+ /* Read each data member type until we find the terminating ';' at the end of
+ the data member list, or break for some other reason such as finding the
+ start of the member function list. */
+
+ while (**pp != ';')
+ {
+ STABS_CONTINUE (pp);
+ /* Get space to record the next field's data. */
+ new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+ make_cleanup (free, new);
+ memset (new, 0, sizeof (struct nextfield));
+ new -> next = fip -> list;
+ fip -> list = new;
+
+ /* Get the field name. */
+ p = *pp;
+ /* If is starts with CPLUS_MARKER it is a special abbreviation, unless
+ the CPLUS_MARKER is followed by an underscore, in which case it is
+ just the name of an anonymous type, which we should handle like any
+ other type name. */
+ if (*p == CPLUS_MARKER && p[1] != '_')
+ {
+ if (!read_cpp_abbrev (fip, pp, type, objfile))
+ return 0;
+ continue;
+ }
+
+ /* Look for the ':' that separates the field name from the field
+ values. Data members are delimited by a single ':', while member
+ functions are delimited by a pair of ':'s. When we hit the member
+ functions (if any), terminate scan loop and return. */
+
+ while (*p != ':' && *p != '\0')
+ {
+ p++;
+ }
+ if (*p == '\0')
+ return 0;
+
+ /* Check to see if we have hit the member functions yet. */
+ if (p[1] == ':')
+ {
+ break;
+ }
+ read_one_struct_field (fip, pp, p, type, objfile);
+ }
+ if (p[1] == ':')
+ {
+ /* chill the list of fields: the last entry (at the head) is a
+ partially constructed entry which we now scrub. */
+ fip -> list = fip -> list -> next;
+ }
+ return 1;
+}
+
+/* The stabs for C++ derived classes contain baseclass information which
+ is marked by a '!' character after the total size. This function is
+ called when we encounter the baseclass marker, and slurps up all the
+ baseclass information.
+
+ Immediately following the '!' marker is the number of base classes that
+ the class is derived from, followed by information for each base class.
+ For each base class, there are two visibility specifiers, a bit offset
+ to the base class information within the derived class, a reference to
+ the type for the base class, and a terminating semicolon.
+
+ A typical example, with two base classes, would be "!2,020,19;0264,21;".
+ ^^ ^ ^ ^ ^ ^ ^
+ Baseclass information marker __________________|| | | | | | |
+ Number of baseclasses __________________________| | | | | | |
+ Visibility specifiers (2) ________________________| | | | | |
+ Offset in bits from start of class _________________| | | | |
+ Type number for base class ___________________________| | | |
+ Visibility specifiers (2) _______________________________| | |
+ Offset in bits from start of class ________________________| |
+ Type number of base class ____________________________________|
+
+ Return 1 for success, 0 for (error-type-inducing) failure. */
+
+static int
+read_baseclasses (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ int i;
+ struct nextfield *new;
+
+ if (**pp != '!')
+ {
+ return 1;
+ }
+ else
+ {
+ /* Skip the '!' baseclass information marker. */
+ (*pp)++;
+ }
+
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ {
+ int nbits;
+ TYPE_N_BASECLASSES (type) = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ return 0;
+ }
+
+#if 0
+ /* Some stupid compilers have trouble with the following, so break
+ it up into simpler expressions. */
+ TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *)
+ TYPE_ALLOC (type, B_BYTES (TYPE_N_BASECLASSES (type)));
+#else
+ {
+ int num_bytes = B_BYTES (TYPE_N_BASECLASSES (type));
+ char *pointer;
+
+ pointer = (char *) TYPE_ALLOC (type, num_bytes);
+ TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
+ }
+#endif /* 0 */
+
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type));
+
+ for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+ {
+ new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+ make_cleanup (free, new);
+ memset (new, 0, sizeof (struct nextfield));
+ new -> next = fip -> list;
+ fip -> list = new;
+ new -> field.bitsize = 0; /* this should be an unpacked field! */
+
+ STABS_CONTINUE (pp);
+ switch (*(*pp)++)
+ {
+ case '0':
+ /* Nothing to do. */
+ break;
+ case '1':
+ SET_TYPE_FIELD_VIRTUAL (type, i);
+ break;
+ default:
+ /* Bad visibility format. */
+ return 0;
+ }
+
+ new -> visibility = *(*pp)++;
+ switch (new -> visibility)
+ {
+ case VISIBILITY_PRIVATE:
+ case VISIBILITY_PROTECTED:
+ case VISIBILITY_PUBLIC:
+ break;
+ default:
+ /* Bad visibility format. */
+ return 0;
+ }
+
+ {
+ int nbits;
+
+ /* The remaining value is the bit offset of the portion of the object
+ corresponding to this baseclass. Always zero in the absence of
+ multiple inheritance. */
+
+ new -> field.bitpos = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ return 0;
+ }
+
+ /* The last piece of baseclass information is the type of the
+ base class. Read it, and remember it's type name as this
+ field's name. */
+
+ new -> field.type = read_type (pp, objfile);
+ new -> field.name = type_name_no_tag (new -> field.type);
+
+ /* skip trailing ';' and bump count of number of fields seen */
+ if (**pp == ';')
+ (*pp)++;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+/* The tail end of stabs for C++ classes that contain a virtual function
+ pointer contains a tilde, a %, and a type number.
+ The type number refers to the base class (possibly this class itself) which
+ contains the vtable pointer for the current class.
+
+ This function is called when we have parsed all the method declarations,
+ so we can look for the vptr base class info. */
+
+static int
+read_tilde_fields (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ register char *p;
+
+ STABS_CONTINUE (pp);
+
+ /* If we are positioned at a ';', then skip it. */
+ if (**pp == ';')
+ {
+ (*pp)++;
+ }
+
+ if (**pp == '~')
+ {
+ (*pp)++;
+
+ if (**pp == '=' || **pp == '+' || **pp == '-')
+ {
+ /* Obsolete flags that used to indicate the presence
+ of constructors and/or destructors. */
+ (*pp)++;
+ }
+
+ /* Read either a '%' or the final ';'. */
+ if (*(*pp)++ == '%')
+ {
+ /* The next number is the type number of the base class
+ (possibly our own class) which supplies the vtable for
+ this class. Parse it out, and search that class to find
+ its vtable pointer, and install those into TYPE_VPTR_BASETYPE
+ and TYPE_VPTR_FIELDNO. */
+
+ struct type *t;
+ int i;
+
+ t = read_type (pp, objfile);
+ p = (*pp)++;
+ while (*p != '\0' && *p != ';')
+ {
+ p++;
+ }
+ if (*p == '\0')
+ {
+ /* Premature end of symbol. */
+ return 0;
+ }
+
+ TYPE_VPTR_BASETYPE (type) = t;
+ if (type == t) /* Our own class provides vtbl ptr */
+ {
+ 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;
+ goto gotit;
+ }
+ }
+ /* Virtual function table field not found. */
+ complain (&vtbl_notfound_complaint, TYPE_NAME (type));
+ return 0;
+ }
+ else
+ {
+ TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
+ }
+
+ gotit:
+ *pp = p + 1;
+ }
+ }
+ return 1;
+}
+
+static int
+attach_fn_fields_to_type (fip, type)
+ struct field_info *fip;
+ register struct type *type;
+{
+ register int n;
+
+ for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
+ {
+ if (TYPE_CODE (TYPE_BASECLASS (type, n)) == TYPE_CODE_UNDEF)
+ {
+ /* @@ Memory leak on objfile -> type_obstack? */
+ return 0;
+ }
+ TYPE_NFN_FIELDS_TOTAL (type) +=
+ TYPE_NFN_FIELDS_TOTAL (TYPE_BASECLASS (type, n));
+ }
+
+ for (n = TYPE_NFN_FIELDS (type);
+ fip -> fnlist != NULL;
+ fip -> fnlist = fip -> fnlist -> next)
+ {
+ --n; /* Circumvent Sun3 compiler bug */
+ TYPE_FN_FIELDLISTS (type)[n] = fip -> fnlist -> fn_fieldlist;
+ }
+ return 1;
+}
+
+/* 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. */
+
+static int
+attach_fields_to_type (fip, type, objfile)
+ struct field_info *fip;
+ register struct type *type;
+ struct objfile *objfile;
+{
+ register int nfields = 0;
+ register int non_public_fields = 0;
+ register struct nextfield *scan;
+
+ /* Count up the number of fields that we have, as well as taking note of
+ whether or not there are any non-public fields, which requires us to
+ allocate and build the private_field_bits and protected_field_bits
+ bitfields. */
+
+ for (scan = fip -> list; scan != NULL; scan = scan -> next)
+ {
+ nfields++;
+ if (scan -> visibility != VISIBILITY_PUBLIC)
+ {
+ non_public_fields++;
+ }
+ }
+
+ /* Now we know how many fields there are, and whether or not there are any
+ non-public fields. Record the field count, allocate space for the
+ array of fields, and create blank visibility bitfields if necessary. */
+
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nfields);
+ memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+
+ if (non_public_fields)
+ {
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+
+ TYPE_FIELD_PRIVATE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
+
+ TYPE_FIELD_PROTECTED_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
+ }
+
+ /* Copy the saved-up fields into the field vector. Start from the head
+ of the list, adding to the tail of the field array, so that they end
+ up in the same order in the array in which they were added to the list. */
+
+ while (nfields-- > 0)
+ {
+ TYPE_FIELD (type, nfields) = fip -> list -> field;
+ switch (fip -> list -> visibility)
+ {
+ case VISIBILITY_PRIVATE:
+ SET_TYPE_FIELD_PRIVATE (type, nfields);
+ break;
+
+ case VISIBILITY_PROTECTED:
+ SET_TYPE_FIELD_PROTECTED (type, nfields);
+ break;
+
+ case VISIBILITY_PUBLIC:
+ break;
+
+ default:
+ /* Should warn about this unknown visibility? */
+ break;
+ }
+ fip -> list = fip -> list -> next;
+ }
+ return 1;
+}
+
+/* Read the description of a structure (or union type) and return an object
+ describing the type.
+
+ PP points to a character pointer that points to the next unconsumed token
+ in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;",
+ *PP will point to "4a:1,0,32;;".
+
+ TYPE points to an incomplete type that needs to be filled in.
+
+ OBJFILE points to the current objfile from which the stabs information is
+ being read. (Note that it is redundant in that TYPE also contains a pointer
+ to this same objfile, so it might be a good idea to eliminate it. FIXME).
+ */
+
+static struct type *
+read_struct_type (pp, type, objfile)
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ struct cleanup *back_to;
+ struct field_info fi;
+
+ fi.list = NULL;
+ fi.fnlist = NULL;
+
+ back_to = make_cleanup (null_cleanup, 0);
+
+ INIT_CPLUS_SPECIFIC (type);
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+
+ /* First comes the total size in bytes. */
+
+ {
+ int nbits;
+ TYPE_LENGTH (type) = read_huge_number (pp, 0, &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+ }
+
+ /* Now read the baseclasses, if any, read the regular C struct or C++
+ class member fields, attach the fields to the type, read the C++
+ member functions, attach them to the type, and then read any tilde
+ field (baseclass specifier for the class holding the main vtable). */
+
+ if (!read_baseclasses (&fi, pp, type, objfile)
+ || !read_struct_fields (&fi, pp, type, objfile)
+ || !attach_fields_to_type (&fi, type, objfile)
+ || !read_member_functions (&fi, pp, type, objfile)
+ || !attach_fn_fields_to_type (&fi, type)
+ || !read_tilde_fields (&fi, pp, type, objfile))
+ {
+ do_cleanups (back_to);
+ return (error_type (pp));
+ }
+
+ do_cleanups (back_to);
+ 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, objfile)
+ register char **pp;
+ register struct type *type;
+ struct objfile *objfile;
+{
+ struct type *index_type, *element_type, *range_type;
+ int lower, upper;
+ int adjustable = 0;
+ int nbits;
+
+ /* 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, objfile);
+ if (**pp != ';')
+ /* Improper format of array type decl. */
+ return error_type (pp);
+ ++*pp;
+
+ if (!(**pp >= '0' && **pp <= '9'))
+ {
+ (*pp)++;
+ adjustable = 1;
+ }
+ lower = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+
+ if (!(**pp >= '0' && **pp <= '9'))
+ {
+ (*pp)++;
+ adjustable = 1;
+ }
+ upper = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+
+ element_type = read_type (pp, objfile);
+
+ if (adjustable)
+ {
+ lower = 0;
+ upper = -1;
+ }
+
+ range_type =
+ create_range_type ((struct type *) NULL, index_type, lower, upper);
+ type = create_array_type (type, element_type, range_type);
+
+ /* If we have an array whose element type is not yet known, but whose
+ bounds *are* known, record it to be adjusted at the end of the file. */
+
+ if (TYPE_LENGTH (element_type) == 0 && !adjustable)
+ {
+ add_undefined_type (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, objfile)
+ register char **pp;
+ register struct type *type;
+ struct objfile *objfile;
+{
+ 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 0
+ /* FIXME! The stabs produced by Sun CC merrily define things that ought
+ to be file-scope, between N_FN entries, using N_LSYM. What's a mother
+ to do? For now, force all enum values to file scope. */
+ if (within_function)
+ symlist = &local_symbols;
+ else
+#endif
+ 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 comma instead of a NAME means the end. */
+ while (**pp && **pp != ';' && **pp != ',')
+ {
+ int nbits;
+ STABS_CONTINUE (pp);
+ p = *pp;
+ while (*p != ':') p++;
+ name = obsavestring (*pp, p - *pp, &objfile -> symbol_obstack);
+ *pp = p + 1;
+ n = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+
+ sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = name;
+ SYMBOL_LANGUAGE (sym) = current_subfile -> language;
+ 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_FLAGS (type) &= ~TYPE_FLAG_STUB;
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nsyms);
+ memset (TYPE_FIELDS (type), 0, 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 *xsym = syms->symbol[j];
+ SYMBOL_TYPE (xsym) = type;
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym);
+ TYPE_FIELD_VALUE (type, n) = 0;
+ TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym);
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+#if 0
+ /* This screws up perfectly good C programs with enums. FIXME. */
+ /* Is this Modula-2's BOOLEAN type? Flag it as such if so. */
+ if(TYPE_NFIELDS(type) == 2 &&
+ ((STREQ(TYPE_FIELD_NAME(type,0),"TRUE") &&
+ STREQ(TYPE_FIELD_NAME(type,1),"FALSE")) ||
+ (STREQ(TYPE_FIELD_NAME(type,1),"TRUE") &&
+ STREQ(TYPE_FIELD_NAME(type,0),"FALSE"))))
+ TYPE_CODE(type) = TYPE_CODE_BOOL;
+#endif
+
+ return type;
+}
+
+/* Sun's ACC uses a somewhat saner method for specifying the builtin
+ typedefs in every file (for int, long, etc):
+
+ type = b <signed> <width>; <offset>; <nbits>
+ signed = u or s. Possible c in addition to u or s (for char?).
+ offset = offset from high order bit to start bit of type.
+ width is # bytes in object of this type, nbits is # bits in type.
+
+ The width/offset stuff appears to be for small objects stored in
+ larger ones (e.g. `shorts' in `int' registers). We ignore it for now,
+ FIXME. */
+
+static struct type *
+read_sun_builtin_type (pp, typenums, objfile)
+ char **pp;
+ int typenums[2];
+ struct objfile *objfile;
+{
+ int type_bits;
+ int nbits;
+ int signed_type;
+
+ switch (**pp)
+ {
+ case 's':
+ signed_type = 1;
+ break;
+ case 'u':
+ signed_type = 0;
+ break;
+ default:
+ return error_type (pp);
+ }
+ (*pp)++;
+
+ /* For some odd reason, all forms of char put a c here. This is strange
+ because no other type has this honor. We can safely ignore this because
+ we actually determine 'char'acterness by the number of bits specified in
+ the descriptor. */
+
+ if (**pp == 'c')
+ (*pp)++;
+
+ /* The first number appears to be the number of bytes occupied
+ by this type, except that unsigned short is 4 instead of 2.
+ Since this information is redundant with the third number,
+ we will ignore it. */
+ read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+
+ /* The second number is always 0, so ignore it too. */
+ read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+
+ /* The third number is the number of bits for this type. */
+ type_bits = read_huge_number (pp, 0, &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+
+#if 0
+ /* FIXME. Here we should just be able to make a type of the right
+ number of bits and signedness. FIXME. */
+
+ if (type_bits == TARGET_LONG_LONG_BIT)
+ return (lookup_fundamental_type (objfile,
+ signed_type? FT_LONG_LONG: FT_UNSIGNED_LONG_LONG));
+
+ if (type_bits == TARGET_INT_BIT)
+ {
+ /* FIXME -- the only way to distinguish `int' from `long'
+ is to look at its name! */
+ if (signed_type)
+ {
+ if (long_kludge_name && long_kludge_name[0] == 'l' /* long */)
+ return lookup_fundamental_type (objfile, FT_LONG);
+ else
+ return lookup_fundamental_type (objfile, FT_INTEGER);
+ }
+ else
+ {
+ if (long_kludge_name
+ && ((long_kludge_name[0] == 'u' /* unsigned */ &&
+ long_kludge_name[9] == 'l' /* long */)
+ || (long_kludge_name[0] == 'l' /* long unsigned */)))
+ return lookup_fundamental_type (objfile, FT_UNSIGNED_LONG);
+ else
+ return lookup_fundamental_type (objfile, FT_UNSIGNED_INTEGER);
+ }
+ }
+
+ if (type_bits == TARGET_SHORT_BIT)
+ return (lookup_fundamental_type (objfile,
+ signed_type? FT_SHORT: FT_UNSIGNED_SHORT));
+
+ if (type_bits == TARGET_CHAR_BIT)
+ return (lookup_fundamental_type (objfile,
+ signed_type? FT_CHAR: FT_UNSIGNED_CHAR));
+
+ if (type_bits == 0)
+ return lookup_fundamental_type (objfile, FT_VOID);
+
+ return error_type (pp);
+#else
+ return init_type (type_bits == 0 ? TYPE_CODE_VOID : TYPE_CODE_INT,
+ type_bits / TARGET_CHAR_BIT,
+ signed_type ? 0 : TYPE_FLAG_UNSIGNED, (char *)NULL,
+ objfile);
+#endif
+}
+
+static struct type *
+read_sun_floating_type (pp, typenums, objfile)
+ char **pp;
+ int typenums[2];
+ struct objfile *objfile;
+{
+ int nbits;
+ int details;
+ int nbytes;
+
+ /* The first number has more details about the type, for example
+ FN_COMPLEX. */
+ details = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+
+ /* The second number is the number of bytes occupied by this type */
+ nbytes = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp);
+
+ if (details == NF_COMPLEX || details == NF_COMPLEX16
+ || details == NF_COMPLEX32)
+ /* This is a type we can't handle, but we do know the size.
+ We also will be able to give it a name. */
+ return init_type (TYPE_CODE_ERROR, nbytes, 0, NULL, objfile);
+
+ return init_type (TYPE_CODE_FLT, nbytes, 0, NULL, objfile);
+}
+
+/* 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 *BITS to 0 and return the value.
+ If not, set *BITS to be the number of bits in the number and return 0.
+
+ If encounter garbage, set *BITS to -1 and return 0. */
+
+static long
+read_huge_number (pp, end, bits)
+ char **pp;
+ int end;
+ int *bits;
+{
+ char *p = *pp;
+ int sign = 1;
+ long n = 0;
+ int radix = 10;
+ char overflow = 0;
+ int nbits = 0;
+ int c;
+ long upper_limit;
+
+ 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++;
+ }
+
+ upper_limit = LONG_MAX / radix;
+ while ((c = *p++) >= '0' && c < ('0' + radix))
+ {
+ if (n <= upper_limit)
+ {
+ 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 0;
+ }
+ }
+ 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 0;
+ }
+
+ /* -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 (bits)
+ *bits = 0;
+ return n * sign;
+ }
+ /* It's *BITS which has the interesting information. */
+ return 0;
+}
+
+static struct type *
+read_range_type (pp, typenums, objfile)
+ char **pp;
+ int typenums[2];
+ struct objfile *objfile;
+{
+ int rangenums[2];
+ long n2, n3;
+ int n2bits, n3bits;
+ int self_subrange;
+ struct type *result_type;
+ struct type *index_type;
+
+ /* First comes a type we are a subrange of.
+ In C it is usually 0, 1 or the type being defined. */
+ /* FIXME: according to stabs.texinfo and AIX doc, this can be a type-id
+ not just a type number. */
+ if (read_type_number (pp, rangenums) != 0)
+ return error_type (pp);
+ 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. */
+ n2 = read_huge_number (pp, ';', &n2bits);
+ n3 = read_huge_number (pp, ';', &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 = 0;
+
+ /* 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. Take care of the case where <large number> doesn't
+ fit in a long but <large number>-1 does. */
+ else if ((n2bits != 0 && n3bits != 0 && n2bits == n3bits + 1)
+ || (n2bits != 0 && n3bits == 0
+ && (n2bits == sizeof (long) * HOST_CHAR_BIT)
+ && n3 == LONG_MAX))
+ {
+ got_signed = 1;
+ nbits = n2bits;
+ }
+
+ if (got_signed || got_unsigned)
+ {
+ return init_type (TYPE_CODE_INT, nbits / TARGET_CHAR_BIT,
+ got_unsigned ? TYPE_FLAG_UNSIGNED : 0, NULL,
+ objfile);
+ }
+ 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 init_type (TYPE_CODE_VOID, 0, 0, NULL, objfile);
+
+ /* 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!
+
+ GDB does not have complex types.
+
+ Just return the complex as a float of that size. It won't work right
+ for the complex values, but at least it makes the file loadable. */
+
+ if (n3 == 0 && n2 > 0)
+ {
+ return init_type (TYPE_CODE_FLT, n2, 0, NULL, objfile);
+ }
+
+ /* If the upper bound is -1, it must really be an unsigned int. */
+
+ else if (n2 == 0 && n3 == -1)
+ {
+ /* It is unsigned int or unsigned long. */
+ /* GCC 2.3.3 uses this for long long too, but that is just a GDB 3.5
+ compatibility hack. */
+ return init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, NULL, objfile);
+ }
+
+ /* 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 init_type (TYPE_CODE_INT, 1, 0, NULL, objfile);
+
+ /* We used to do this only for subrange of self or subrange of int. */
+ else if (n2 == 0)
+ {
+ if (n3 < 0)
+ /* n3 actually gives the size. */
+ return init_type (TYPE_CODE_INT, - n3, TYPE_FLAG_UNSIGNED,
+ NULL, objfile);
+ if (n3 == 0xff)
+ return init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED, NULL, objfile);
+ if (n3 == 0xffff)
+ return init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED, NULL, objfile);
+
+ /* -1 is used for the upper bound of (4 byte) "unsigned int" and
+ "unsigned long", and we already checked for that,
+ so don't need to test for it here. */
+ }
+ /* I think this is for Convex "long long". Since I don't know whether
+ Convex sets self_subrange, I also accept that particular size regardless
+ of self_subrange. */
+ else if (n3 == 0 && n2 < 0
+ && (self_subrange
+ || n2 == - TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT))
+ return init_type (TYPE_CODE_INT, - n2, 0, NULL, objfile);
+ else if (n2 == -n3 -1)
+ {
+ if (n3 == 0x7f)
+ return init_type (TYPE_CODE_INT, 1, 0, NULL, objfile);
+ if (n3 == 0x7fff)
+ return init_type (TYPE_CODE_INT, 2, 0, NULL, objfile);
+ if (n3 == 0x7fffffff)
+ return init_type (TYPE_CODE_INT, 4, 0, NULL, objfile);
+ }
+
+ /* 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);
+
+ index_type = *dbx_lookup_type (rangenums);
+ if (index_type == NULL)
+ {
+ /* Does this actually ever happen? Is that why we are worrying
+ about dealing with it rather than just calling error_type? */
+
+ static struct type *range_type_index;
+
+ complain (&range_type_base_complaint, rangenums[1]);
+ if (range_type_index == NULL)
+ range_type_index =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "range type index type", NULL);
+ index_type = range_type_index;
+ }
+
+ result_type = create_range_type ((struct type *) NULL, index_type, n2, n3);
+ return (result_type);
+}
+
+/* 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, objfile)
+ char **pp;
+ int end;
+ struct objfile *objfile;
+{
+ /* FIXME! Remove this arbitrary limit! */
+ 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)++;
+ STABS_CONTINUE (pp);
+ types[n++] = read_type (pp, objfile);
+ }
+ (*pp)++; /* 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 *));
+ memset (rval + n, 0, sizeof (struct type *));
+ }
+ else
+ {
+ rval = (struct type **) xmalloc (n * sizeof (struct type *));
+ }
+ memcpy (rval, types, n * sizeof (struct type *));
+ return rval;
+}
+
+/* Common block handling. */
+
+/* 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. */
+
+static struct pending *common_block;
+static int common_block_i;
+
+/* Name of the current common block. We get it from the BCOMM instead of the
+ ECOMM to match IBM documentation (even though IBM puts the name both places
+ like everyone else). */
+static char *common_block_name;
+
+/* Process a N_BCOMM symbol. The storage for NAME is not guaranteed
+ to remain after this function returns. */
+
+void
+common_block_start (name, objfile)
+ char *name;
+ struct objfile *objfile;
+{
+ if (common_block_name != NULL)
+ {
+ static struct complaint msg = {
+ "Invalid symbol data: common block within common block",
+ 0, 0};
+ complain (&msg);
+ }
+ common_block = local_symbols;
+ common_block_i = local_symbols ? local_symbols->nsyms : 0;
+ common_block_name = obsavestring (name, strlen (name),
+ &objfile -> symbol_obstack);
+}
+
+/* Process a N_ECOMM symbol. */
+
+void
+common_block_end (objfile)
+ struct objfile *objfile;
+{
+ /* Symbols declared since the BCOMM are to have the common block
+ start address added in when we know it. common_block and
+ common_block_i point 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 pending *new = 0;
+ struct pending *next;
+ int j;
+
+ if (common_block_name == NULL)
+ {
+ static struct complaint msg = {"ECOMM symbol unmatched by BCOMM", 0, 0};
+ complain (&msg);
+ return;
+ }
+
+ sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = common_block_name;
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+
+ /* Now we copy all the symbols which have been defined since the BCOMM. */
+
+ /* Copy all the struct pendings before common_block. */
+ for (next = local_symbols;
+ next != NULL && next != common_block;
+ next = next->next)
+ {
+ for (j = 0; j < next->nsyms; j++)
+ add_symbol_to_list (next->symbol[j], &new);
+ }
+
+ /* Copy however much of COMMON_BLOCK we need. If COMMON_BLOCK is
+ NULL, it means copy all the local symbols (which we already did
+ above). */
+
+ if (common_block != NULL)
+ for (j = common_block_i; j < common_block->nsyms; j++)
+ add_symbol_to_list (common_block->symbol[j], &new);
+
+ SYMBOL_NAMESPACE (sym) = (enum namespace)((long) new);
+
+ /* Should we be putting local_symbols back to what it was?
+ Does it matter? */
+
+ i = hashname (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
+ global_sym_chain[i] = sym;
+ common_block_name = NULL;
+}
+
+/* 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;
+ }
+}
+
+
+
+/* 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. */
+
+void
+add_undefined_type (type)
+ struct type *type;
+{
+ if (undef_types_length == undef_types_allocated)
+ {
+ undef_types_allocated *= 2;
+ undef_types = (struct type **)
+ xrealloc ((char *) undef_types,
+ undef_types_allocated * sizeof (struct type *));
+ }
+ undef_types[undef_types_length++] = type;
+}
+
+/* Go through each undefined type, see if it's still undefined, and fix it
+ up if possible. We have two kinds of undefined types:
+
+ TYPE_CODE_ARRAY: Array whose target type wasn't defined yet.
+ Fix: update array length using the element bounds
+ and the target type's length.
+ TYPE_CODE_STRUCT, TYPE_CODE_UNION: Structure whose fields were not
+ yet defined at the time a pointer to it was made.
+ Fix: Do a full lookup on the struct/union tag. */
+void
+cleanup_undefined_types ()
+{
+ struct type **type;
+
+ for (type = undef_types; type < undef_types + undef_types_length; type++)
+ {
+ switch (TYPE_CODE (*type))
+ {
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ {
+ /* Check if it has been defined since. */
+ if (TYPE_FLAGS (*type) & TYPE_FLAG_STUB)
+ {
+ struct pending *ppt;
+ int i;
+ /* Name of the type, without "struct" or "union" */
+ char *typename = TYPE_TAG_NAME (*type);
+
+ if (typename == NULL)
+ {
+ static struct complaint msg = {"need a type name", 0, 0};
+ complain (&msg);
+ break;
+ }
+ 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))
+ && STREQ (SYMBOL_NAME (sym), typename))
+ {
+ memcpy (*type, SYMBOL_TYPE (sym),
+ sizeof (struct type));
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case TYPE_CODE_ARRAY:
+ {
+ struct type *range_type;
+ int lower, upper;
+
+ if (TYPE_LENGTH (*type) != 0) /* Better be unknown */
+ goto badtype;
+ if (TYPE_NFIELDS (*type) != 1)
+ goto badtype;
+ range_type = TYPE_FIELD_TYPE (*type, 0);
+ if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
+ goto badtype;
+
+ /* Now recompute the length of the array type, based on its
+ number of elements and the target type's length. */
+ lower = TYPE_FIELD_BITPOS (range_type, 0);
+ upper = TYPE_FIELD_BITPOS (range_type, 1);
+ TYPE_LENGTH (*type) = (upper - lower + 1)
+ * TYPE_LENGTH (TYPE_TARGET_TYPE (*type));
+ }
+ break;
+
+ default:
+ badtype:
+ {
+ static struct complaint msg = {"\
+GDB internal error. cleanup_undefined_types with bad type %d.", 0, 0};
+ complain (&msg, TYPE_CODE (*type));
+ }
+ break;
+ }
+ }
+ undef_types_length = 0;
+}
+
+/* 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 minimal symbol table. */
+
+void
+scan_file_globals (objfile)
+ struct objfile *objfile;
+{
+ int hash;
+ struct minimal_symbol *msymbol;
+ struct symbol *sym, *prev;
+
+ if (objfile->msymbols == 0) /* Beware the null file. */
+ return;
+
+ for (msymbol = objfile -> msymbols; SYMBOL_NAME (msymbol) != NULL; msymbol++)
+ {
+ QUIT;
+
+ prev = NULL;
+
+ /* Get the hash index and check all the symbols
+ under that hash index. */
+
+ hash = hashname (SYMBOL_NAME (msymbol));
+
+ for (sym = global_sym_chain[hash]; sym;)
+ {
+ if (SYMBOL_NAME (msymbol)[0] == SYMBOL_NAME (sym)[0] &&
+ STREQ(SYMBOL_NAME (msymbol) + 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, SYMBOL_VALUE_ADDRESS (msymbol));
+ }
+ else
+ {
+ SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+
+ if (prev)
+ {
+ sym = SYMBOL_VALUE_CHAIN (prev);
+ }
+ else
+ {
+ sym = global_sym_chain[hash];
+ }
+ }
+ else
+ {
+ prev = sym;
+ sym = SYMBOL_VALUE_CHAIN (sym);
+ }
+ }
+ }
+}
+
+/* Initialize anything that needs initializing when starting to read
+ a fresh piece of a symbol file, e.g. reading in the stuff corresponding
+ to a psymtab. */
+
+void
+stabsread_init ()
+{
+}
+
+/* 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
+stabsread_new_init ()
+{
+ /* Empty the hash table of global syms looking for values. */
+ memset (global_sym_chain, 0, sizeof (global_sym_chain));
+}
+
+/* Initialize anything that needs initializing at the same time as
+ start_symtab() is called. */
+
+void start_stabs ()
+{
+ global_stabs = NULL; /* AIX COFF */
+ /* Leave FILENUM of 0 free for builtin types and this file's types. */
+ n_this_object_header_files = 1;
+ type_vector_length = 0;
+ type_vector = (struct type **) 0;
+
+ /* FIXME: If common_block_name is not already NULL, we should complain(). */
+ common_block_name = NULL;
+}
+
+/* Call after end_symtab() */
+
+void end_stabs ()
+{
+ if (type_vector)
+ {
+ free ((char *) type_vector);
+ }
+ type_vector = 0;
+ type_vector_length = 0;
+ previous_stab_code = 0;
+}
+
+void
+finish_global_stabs (objfile)
+ struct objfile *objfile;
+{
+ if (global_stabs)
+ {
+ patch_block_stabs (global_symbols, global_stabs, objfile);
+ free ((PTR) global_stabs);
+ global_stabs = NULL;
+ }
+}
+
+/* Initializer for this module */
+
+void
+_initialize_stabsread ()
+{
+ undef_types_allocated = 20;
+ undef_types_length = 0;
+ undef_types = (struct type **)
+ xmalloc (undef_types_allocated * sizeof (struct type *));
+}
diff --git a/gnu/usr.bin/gdb/gdb/stabsread.h b/gnu/usr.bin/gdb/gdb/stabsread.h
new file mode 100644
index 000000000000..3b890d805840
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/stabsread.h
@@ -0,0 +1,194 @@
+/* Include file for stabs debugging format support functions.
+ Copyright 1986-1991, 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Definitions, prototypes, etc for stabs debugging format support
+ functions.
+
+ Variables declared in this file can be defined by #define-ing
+ the name EXTERN to null. It is used to declare variables that
+ are normally extern, but which get defined in a single module
+ using this technique. */
+
+#ifndef EXTERN
+#define EXTERN extern
+#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
+
+/* 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. */
+
+EXTERN struct symbol *global_sym_chain[HASHSIZE];
+
+extern void common_block_start PARAMS ((char *, struct objfile *));
+extern void common_block_end PARAMS ((struct objfile *));
+
+/* Kludge for xcoffread.c */
+
+struct pending_stabs
+{
+ int count;
+ int length;
+ char *stab[1];
+};
+
+EXTERN struct pending_stabs *global_stabs;
+
+/* The type code that process_one_symbol saw on its previous invocation.
+ Used to detect pairs of N_SO symbols. */
+
+EXTERN int previous_stab_code;
+
+/* 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
+{
+
+ /* Name of header file */
+
+ char *name;
+
+ /* Numeric code distinguishing instances of one header file that produced
+ different results when included. It comes from the N_BINCL or N_EXCL. */
+
+ int instance;
+
+ /* Pointer to vector of types */
+
+ struct type **vector;
+
+ /* Allocated length (# elts) of that vector */
+
+ int length;
+
+};
+
+EXTERN struct header_file *header_files;
+
+EXTERN int n_header_files;
+
+EXTERN int n_allocated_header_files;
+
+/* 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. */
+
+EXTERN int *this_object_header_files;
+
+EXTERN int n_this_object_header_files;
+
+EXTERN int n_allocated_this_object_header_files;
+
+extern struct complaint unknown_symtype_complaint;
+extern struct complaint unknown_symchar_complaint;
+
+extern struct type *
+read_type PARAMS ((char **, struct objfile *));
+
+extern void
+cleanup_undefined_types PARAMS ((void));
+
+extern struct type **
+dbx_lookup_type PARAMS ((int [2]));
+
+extern long
+read_number PARAMS ((char **, int));
+
+extern void
+add_undefined_type PARAMS ((struct type *));
+
+extern struct symbol *
+define_symbol PARAMS ((CORE_ADDR, char *, int, int, struct objfile *));
+
+extern void
+stabsread_init PARAMS ((void));
+
+extern void
+stabsread_new_init PARAMS ((void));
+
+extern void
+start_stabs PARAMS ((void));
+
+extern void
+end_stabs PARAMS ((void));
+
+extern void
+finish_global_stabs PARAMS ((struct objfile *objfile));
+
+/* Functions exported by dbxread.c. These are not in stabsread.h because
+ they are only used by some stabs readers. */
+
+extern struct partial_symtab *
+start_psymtab PARAMS ((struct objfile *, struct section_offsets *, char *,
+ CORE_ADDR, int, struct partial_symbol *,
+ struct partial_symbol *));
+
+extern struct partial_symtab *
+end_psymtab PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
+ struct partial_symtab **, int));
+
+extern void
+process_one_symbol PARAMS ((int, int, CORE_ADDR, char *,
+ struct section_offsets *, struct objfile *));
+
+extern void
+elfstab_build_psymtabs PARAMS ((struct objfile *objfile,
+ struct section_offsets *section_offsets,
+ int mainline,
+ file_ptr staboff, unsigned int stabsize,
+ file_ptr stabstroffset,
+ unsigned int stabstrsize));
+
+extern void
+pastab_build_psymtabs PARAMS ((struct objfile *, struct section_offsets *,
+ int));
+
+#undef EXTERN
diff --git a/gnu/usr.bin/gdb/gdb/stack.c b/gnu/usr.bin/gdb/gdb/stack.c
new file mode 100644
index 000000000000..6fdd8c181245
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/stack.c
@@ -0,0 +1,1379 @@
+/* Print and select stack frames for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "value.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "language.h"
+#include "frame.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "breakpoint.h"
+#include "demangle.h"
+#include "inferior.h"
+
+static void
+return_command PARAMS ((char *, int));
+
+static void
+down_command PARAMS ((char *, int));
+
+static void
+down_silently_command PARAMS ((char *, int));
+
+static void
+up_command PARAMS ((char *, int));
+
+static void
+up_silently_command PARAMS ((char *, int));
+
+static void
+frame_command PARAMS ((char *, int));
+
+static void
+select_frame_command PARAMS ((char *, int));
+
+static void
+args_info PARAMS ((char *, int));
+
+static void
+print_frame_arg_vars PARAMS ((FRAME, FILE *));
+
+static void
+catch_info PARAMS ((char *, int));
+
+static void
+locals_info PARAMS ((char *, int));
+
+static void
+print_frame_label_vars PARAMS ((FRAME, int, FILE *));
+
+static void
+print_frame_local_vars PARAMS ((FRAME, FILE *));
+
+static int
+print_block_frame_labels PARAMS ((struct block *, int *, FILE *));
+
+static int
+print_block_frame_locals PARAMS ((struct block *, FRAME, FILE *));
+
+static void
+backtrace_command PARAMS ((char *, int));
+
+static FRAME
+parse_frame_specification PARAMS ((char *));
+
+static void
+frame_info PARAMS ((char *, int));
+
+
+extern int addressprint; /* Print addresses, or stay symbolic only? */
+extern int info_verbose; /* Verbosity of symbol reading msgs */
+extern int lines_to_list; /* # of lines "list" command shows by default */
+
+/* The "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;
+
+
+struct print_stack_frame_args {
+ struct frame_info *fi;
+ int level;
+ int source;
+ int args;
+};
+
+static int print_stack_frame_stub PARAMS ((char *));
+
+/* Pass the args the way catch_errors wants them. */
+static int
+print_stack_frame_stub (args)
+ char *args;
+{
+ struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
+ print_frame_info (p->fi, p->level, p->source, p->args);
+ return 0;
+}
+
+/* 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. */
+
+void
+print_stack_frame (frame, level, source)
+ FRAME frame;
+ int level;
+ int source;
+{
+ struct print_stack_frame_args args;
+
+ args.fi = get_frame_info (frame);
+ args.level = level;
+ args.source = source;
+ args.args = 1;
+
+ catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ERROR);
+}
+
+struct print_args_args {
+ struct symbol *func;
+ struct frame_info *fi;
+};
+
+static int print_args_stub PARAMS ((char *));
+
+/* Pass the args the way catch_errors wants them. */
+static int
+print_args_stub (args)
+ char *args;
+{
+ int numargs;
+ struct print_args_args *p = (struct print_args_args *)args;
+ FRAME_NUM_ARGS (numargs, (p->fi));
+ print_frame_args (p->func, p->fi, numargs, stdout);
+ return 0;
+}
+
+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;
+ enum language funlang = language_unknown;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ CORE_ADDR sp;
+
+ /* Get the value of SP_REGNUM relative to the frame. */
+ get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL,
+ FRAME_INFO_ID (fi), SP_REGNUM, (enum lval_type *)NULL);
+ sp = extract_address (buf, REGISTER_RAW_SIZE (SP_REGNUM));
+
+ /* This is not a perfect test, because if a function alloca's some
+ memory, puts some code there, and then jumps into it, then the test
+ will succeed even though there is no call dummy. Probably best is
+ to check for a bp_call_dummy breakpoint. */
+ if (PC_IN_CALL_DUMMY (fi->pc, sp, fi->frame))
+ {
+ /* Do this regardless of SOURCE because we don't have any source
+ to list for this frame. */
+ if (level >= 0)
+ printf_filtered ("#%-2d ", level);
+ printf_filtered ("<function called from gdb>\n");
+ return;
+ }
+ if (fi->signal_handler_caller)
+ {
+ /* Do this regardless of SOURCE because we don't have any source
+ to list for this frame. */
+ if (level >= 0)
+ printf_filtered ("#%-2d ", level);
+ printf_filtered ("<signal handler called>\n");
+ return;
+ }
+
+ /* If fi is not the innermost frame, that normally means that fi->pc
+ points to *after* the call instruction, and we want to get the line
+ containing the call, never the next line. But if the next frame is
+ a signal_handler_caller frame, then the next frame was not entered
+ as the result of a call, and we want to get the line containing
+ fi->pc. */
+ sal =
+ find_pc_line (fi->pc,
+ fi->next != NULL && fi->next->signal_handler_caller == 0);
+
+ 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). This also occurs if the user uses asm() to create
+ a function but not stabs for it (in a file compiled -g).
+
+ So look in the minimal symbol tables 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 minimal symbols in the middle of a function; if this is
+ ever changed many parts of GDB will need to be changed (and we'll
+ create a find_pc_minimal_function or some such). */
+
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL
+ && (SYMBOL_VALUE_ADDRESS (msymbol)
+ > 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 = SYMBOL_NAME (msymbol);
+ funlang = SYMBOL_LANGUAGE (msymbol);
+ }
+ else
+ {
+ funname = SYMBOL_NAME (func);
+ funlang = SYMBOL_LANGUAGE (func);
+ }
+ }
+ else
+ {
+ register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL)
+ {
+ funname = SYMBOL_NAME (msymbol);
+ funlang = SYMBOL_LANGUAGE (msymbol);
+ }
+ }
+
+ if (source >= 0 || !sal.symtab)
+ {
+ if (level >= 0)
+ printf_filtered ("#%-2d ", level);
+ if (addressprint)
+ if (fi->pc != sal.pc || !sal.symtab)
+ printf_filtered ("%s in ", local_hex_string((unsigned long) fi->pc));
+ fprintf_symbol_filtered (stdout, funname ? funname : "??", funlang,
+ DMGL_NO_OPTS);
+ wrap_here (" ");
+ fputs_filtered (" (", stdout);
+ if (args)
+ {
+ struct print_args_args args;
+ args.fi = fi;
+ args.func = func;
+ catch_errors (print_args_stub, (char *)&args, "", RETURN_MASK_ERROR);
+ }
+ printf_filtered (")");
+ if (sal.symtab && sal.symtab->filename)
+ {
+ wrap_here (" ");
+ printf_filtered (" at %s:%d", sal.symtab->filename, sal.line);
+ }
+
+#ifdef PC_LOAD_SEGMENT
+ /* If we couldn't print out function name but if can figure out what
+ load segment this pc value is from, at least print out some info
+ about its load segment. */
+ if (!funname) {
+ wrap_here (" ");
+ printf_filtered (" from %s", PC_LOAD_SEGMENT (fi->pc));
+ }
+#endif
+ 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,
+ fi->pc);
+ if (!done)
+ {
+ if (addressprint && mid_statement)
+ printf_filtered ("%s\t", local_hex_string((unsigned long) 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);
+}
+
+/*
+ * Read a frame specification in whatever the appropriate format is.
+ * Call error() if the specification is in any way invalid (i.e.
+ * this function never returns NULL).
+ */
+static FRAME
+parse_frame_specification (frame_exp)
+ char *frame_exp;
+{
+ int numargs = 0;
+#define MAXARGS 4
+ CORE_ADDR args[MAXARGS];
+
+ if (frame_exp)
+ {
+ char *addr_string, *p;
+ struct cleanup *tmp_cleanup;
+
+ while (*frame_exp == ' ') frame_exp++;
+
+ while (*frame_exp)
+ {
+ if (numargs > MAXARGS)
+ error ("Too many args in frame specification");
+ /* Parse an argument. */
+ for (p = frame_exp; *p && *p != ' '; p++)
+ ;
+ addr_string = savestring(frame_exp, p - frame_exp);
+
+ {
+ tmp_cleanup = make_cleanup (free, addr_string);
+ args[numargs++] = parse_and_eval_address (addr_string);
+ do_cleanups (tmp_cleanup);
+ }
+
+ /* Skip spaces, move to possible next arg. */
+ while (*p == ' ') p++;
+ frame_exp = p;
+ }
+ }
+
+ switch (numargs)
+ {
+ case 0:
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+ return selected_frame;
+ /* NOTREACHED */
+ case 1:
+ {
+ int level = args[0];
+ 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) != args[0];
+ fid = get_prev_frame (fid))
+ ;
+
+ if (fid)
+ while ((tfid = get_prev_frame (fid)) &&
+ (FRAME_FP (tfid) == args[0]))
+ fid = tfid;
+
+ /* We couldn't identify the frame as an existing frame, but
+ perhaps we can create one with a single argument.
+ Fall through to default case; it's up to SETUP_ARBITRARY_FRAME
+ to complain if it doesn't like a single arg. */
+ }
+
+ default:
+#ifdef SETUP_ARBITRARY_FRAME
+ return SETUP_ARBITRARY_FRAME (numargs, args);
+#else
+ /* Usual case. Do it here rather than have everyone supply
+ a SETUP_ARBITRARY_FRAME that does this. */
+ if (numargs == 1)
+ return create_new_frame (args[0], 0);
+ error ("Too many args in frame specification");
+#endif
+ /* NOTREACHED */
+ }
+ /* 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, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+ FRAME frame;
+ struct frame_info *fi;
+ struct frame_saved_regs fsr;
+ struct symtab_and_line sal;
+ struct symbol *func;
+ struct symtab *s;
+ FRAME calling_frame;
+ int i, count;
+ char *funname = 0;
+ enum language funlang = language_unknown;
+
+ if (!target_has_stack)
+ error ("No stack.");
+
+ 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 != NULL && fi->next->signal_handler_caller == 0);
+ func = get_frame_function (frame);
+ s = find_pc_symtab(fi->pc);
+ if (func)
+ {
+ funname = SYMBOL_NAME (func);
+ funlang = SYMBOL_LANGUAGE (func);
+ }
+ else
+ {
+ register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL)
+ {
+ funname = SYMBOL_NAME (msymbol);
+ funlang = SYMBOL_LANGUAGE (msymbol);
+ }
+ }
+ calling_frame = get_prev_frame (frame);
+
+ if (!addr_exp && selected_frame_level >= 0) {
+ printf_filtered ("Stack level %d, frame at %s:\n",
+ selected_frame_level,
+ local_hex_string((unsigned long) FRAME_FP(frame)));
+ } else {
+ printf_filtered ("Stack frame at %s:\n",
+ local_hex_string((unsigned long) FRAME_FP(frame)));
+ }
+ printf_filtered (" %s = %s",
+ reg_names[PC_REGNUM],
+ local_hex_string((unsigned long) fi->pc));
+
+ wrap_here (" ");
+ if (funname)
+ {
+ printf_filtered (" in ");
+ fprintf_symbol_filtered (stdout, funname, funlang,
+ DMGL_ANSI | DMGL_PARAMS);
+ }
+ wrap_here (" ");
+ if (sal.symtab)
+ printf_filtered (" (%s:%d)", sal.symtab->filename, sal.line);
+ puts_filtered ("; ");
+ wrap_here (" ");
+ printf_filtered ("saved %s %s\n", reg_names[PC_REGNUM],
+ local_hex_string((unsigned long) FRAME_SAVED_PC (frame)));
+
+ {
+ int frameless = 0;
+#ifdef FRAMELESS_FUNCTION_INVOCATION
+ FRAMELESS_FUNCTION_INVOCATION (fi, frameless);
+#endif
+ if (frameless)
+ printf_filtered (" (FRAMELESS),");
+ }
+
+ if (calling_frame)
+ printf_filtered (" called by frame at %s",
+ local_hex_string((unsigned long) FRAME_FP (calling_frame)));
+ if (fi->next && calling_frame)
+ puts_filtered (",");
+ wrap_here (" ");
+ if (fi->next)
+ printf_filtered (" caller of frame at %s",
+ local_hex_string ((unsigned long) fi->next->frame));
+ if (fi->next || calling_frame)
+ puts_filtered ("\n");
+ if (s)
+ printf_filtered(" source language %s.\n", language_str(s->language));
+
+#ifdef PRINT_EXTRA_FRAME_INFO
+ PRINT_EXTRA_FRAME_INFO (fi);
+#endif
+
+ {
+ /* 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 %s,",
+ local_hex_string((unsigned long) 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");
+ }
+ }
+ {
+ /* Address of the local variables for this frame, or 0. */
+ CORE_ADDR arg_list = FRAME_LOCALS_ADDRESS (fi);
+
+ if (arg_list == 0)
+ printf_filtered (" Locals at unknown address,");
+ else
+ printf_filtered (" Locals at %s,",
+ local_hex_string((unsigned long) arg_list));
+ }
+
+#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 %s\n",
+ local_hex_string((unsigned long) 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 %s", reg_names[i],
+ local_hex_string((unsigned long) 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;
+
+ if (!target_has_stack)
+ error ("No stack.");
+
+ /* 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)
+ 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);
+
+ /* Don't use print_stack_frame; if an error() occurs it probably
+ means further attempts to backtrace would fail (on the other
+ hand, perhaps the code does or could be fixed to make sure
+ the frame->prev field gets set to NULL in that case). */
+ 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");
+}
+
+/* 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;
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream);
+ fputs_filtered (" = ", stream);
+ print_variable_value (sym, frame, stream);
+ fprintf_filtered (stream, "\n");
+ }
+ }
+ return values_printed;
+}
+
+/* Same, but print labels. */
+
+static int
+print_block_frame_labels (b, have_default, stream)
+ struct block *b;
+ 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 (STREQ (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_filtered (SYMBOL_SOURCE_NAME (sym), stream);
+ if (addressprint)
+ fprintf_filtered (stream, " %s",
+ local_hex_string((unsigned long) SYMBOL_VALUE_ADDRESS (sym)));
+ fprintf_filtered (stream, " in file %s, line %d\n",
+ sal.symtab->filename, sal.line);
+ }
+ }
+ 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 void
+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");
+ return;
+ }
+
+ 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");
+ }
+}
+
+/* Same, but print labels. */
+
+static void
+print_frame_label_vars (frame, this_level_only, stream)
+ register FRAME frame;
+ int this_level_only;
+ register FILE *stream;
+{
+ 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");
+ return;
+ }
+
+ bl = blockvector_for_pc (BLOCK_END (block) - 4, &index);
+ blocks_printed = (char *) alloca (BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+ memset (blocks_printed, 0, 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), &have_default, stream))
+ values_printed = 1;
+ blocks_printed[index] = 1;
+ }
+ index++;
+ }
+ if (have_default)
+ return;
+ if (values_printed && this_level_only)
+ return;
+
+ /* 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");
+ }
+}
+
+/* ARGSUSED */
+static void
+locals_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (!selected_frame)
+ error ("No frame selected.");
+ print_frame_local_vars (selected_frame, stdout);
+}
+
+static void
+catch_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (!selected_frame)
+ error ("No frame selected.");
+ print_frame_label_vars (selected_frame, 0, stdout);
+}
+
+static void
+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");
+ return;
+ }
+
+ b = SYMBOL_BLOCK_VALUE (func);
+ nsyms = BLOCK_NSYMS (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_LOCAL_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_BASEREG_ARG:
+ values_printed = 1;
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream);
+ fputs_filtered (" = ", stream);
+
+ /* We have to look up the symbol because arguments can have
+ two entries (one a parameter, one a local) and the one we
+ want is the local, which lookup_symbol will find for us.
+ This includes gcc1 (not gcc2) on the sparc when passing a
+ small structure and gcc2 when the argument type is float
+ and it is passed as a double and converted to float by
+ the prologue (in the latter case the type of the LOC_ARG
+ symbol is double and the type of the LOC_LOCAL symbol is
+ float). There are also LOC_ARG/LOC_REGISTER pairs which
+ are not combined in symbol-reading. */
+
+ sym2 = lookup_symbol (SYMBOL_NAME (sym),
+ b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+ print_variable_value (sym2, frame, stream);
+ fprintf_filtered (stream, "\n");
+ break;
+
+ default:
+ /* Don't worry about things which aren't arguments. */
+ break;
+ }
+ }
+
+ if (!values_printed)
+ {
+ fprintf_filtered (stream, "No arguments.\n");
+ }
+}
+
+static void
+args_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (!selected_frame)
+ error ("No frame selected.");
+ print_frame_arg_vars (selected_frame, stdout);
+}
+
+/* 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;
+{
+ register struct symtab *s;
+
+ selected_frame = frame;
+ selected_frame_level = level;
+
+ /* Ensure that symbols for this frame are read in. Also, determine the
+ source language of this frame, and switch to it if desired. */
+ if (frame)
+ {
+ s = find_pc_symtab (get_frame_info (frame)->pc);
+ if (s
+ && s->language != current_language->la_language
+ && s->language != language_unknown
+ && language_mode == language_mode_auto) {
+ set_language(s->language);
+ }
+ }
+}
+
+/* Store the selected frame and its level into *FRAMEP and *LEVELP.
+ If there is no selected frame, *FRAMEP is set to NULL. */
+
+void
+record_selected_frame (frameaddrp, levelp)
+ FRAME_ADDR *frameaddrp;
+ int *levelp;
+{
+ *frameaddrp = selected_frame ? FRAME_FP (selected_frame) : 0;
+ *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;
+
+ /* 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 is just as simple. */
+ if (*level_offset_ptr < 0)
+ {
+ while (*level_offset_ptr < 0) {
+ frame1 = get_next_frame (frame);
+ if (!frame1)
+ break;
+ frame = frame1;
+ (*level_offset_ptr)++;
+ }
+ }
+ return frame;
+}
+
+/* The "select_frame" command. With no arg, NOP.
+ 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 select it. See parse_frame_specification for more info on proper
+ frame expressions. */
+
+/* ARGSUSED */
+static void
+select_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);
+
+ /* Try to figure out what level this frame is. But if there is
+ no current stack, don't error out -- let the user set one. */
+ frame1 = 0;
+ if (get_current_frame()) {
+ for (frame1 = get_prev_frame (0);
+ frame1 && frame1 != frame;
+ frame1 = get_prev_frame (frame1))
+ level++;
+ }
+
+ if (!frame1)
+ level = 0;
+
+ select_frame (frame, level);
+}
+
+/* The "frame" command. With no arg, print selected frame briefly.
+ With arg, behaves like select_frame and then prints the selected
+ frame. */
+
+static void
+frame_command (level_exp, from_tty)
+ char *level_exp;
+ int from_tty;
+{
+ select_frame_command (level_exp, from_tty);
+ 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. */
+
+/* ARGSUSED */
+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 == 0 || selected_frame == 0)
+ 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. */
+
+/* ARGSUSED */
+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;
+
+ if (target_has_stack == 0 || selected_frame == 0)
+ error ("No stack.");
+
+ 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);
+}
+
+static void
+return_command (retval_exp, from_tty)
+ char *retval_exp;
+ int from_tty;
+{
+ struct symbol *thisfun;
+ FRAME_ADDR selected_frame_addr;
+ CORE_ADDR selected_frame_pc;
+ FRAME frame;
+ value return_value = NULL;
+
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+ thisfun = get_frame_function (selected_frame);
+ selected_frame_addr = FRAME_FP (selected_frame);
+ selected_frame_pc = (get_frame_info (selected_frame))->pc;
+
+ /* Compute the return value (if any -- possibly getting errors here). */
+
+ if (retval_exp)
+ {
+ return_value = parse_and_eval (retval_exp);
+
+ /* Make sure we have fully evaluated it, since
+ it might live in the stack frame we're about to pop. */
+ if (VALUE_LAZY (return_value))
+ value_fetch_lazy (return_value);
+ }
+
+ /* If interactive, require confirmation. */
+
+ if (from_tty)
+ {
+ if (thisfun != 0)
+ {
+ if (!query ("Make %s return now? ", SYMBOL_SOURCE_NAME (thisfun)))
+ {
+ error ("Not confirmed.");
+ /* NOTREACHED */
+ }
+ }
+ 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 (return_value);
+
+ /* If interactive, print the frame that is now current. */
+
+ if (from_tty)
+ frame_command ("0", 1);
+}
+
+/* Gets the language of the current frame. */
+enum language
+get_frame_language()
+{
+ register struct symtab *s;
+ FRAME fr;
+ enum language flang; /* The language of the current frame */
+
+ fr = get_frame_info(selected_frame);
+ if(fr)
+ {
+ s = find_pc_symtab(fr->pc);
+ if(s)
+ flang = s->language;
+ else
+ flang = language_unknown;
+ }
+ else
+ flang = language_unknown;
+
+ return flang;
+}
+
+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_alias ("dow", "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 ("select-frame", class_stack, select_frame_command,
+ "Select a stack frame without printing anything.\n\
+An argument specifies the frame to select.\n\
+It can be a stack frame number or the address of the frame.\n");
+
+ 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/gnu/usr.bin/gdb/gdb/symfile.c b/gnu/usr.bin/gdb/gdb/symfile.c
new file mode 100644
index 000000000000..197c0c3a6221
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/symfile.c
@@ -0,0 +1,1489 @@
+/* Generic symbol file reading for the GNU debugger, GDB.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "target.h"
+#include "value.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcmd.h"
+#include "breakpoint.h"
+#include "language.h"
+#include "complaints.h"
+#include "demangle.h"
+#include "inferior.h" /* for write_pc */
+
+#include <obstack.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* Global variables owned by this file */
+
+int readnow_symbol_files; /* Read full symbols immediately */
+
+struct complaint oldsyms_complaint = {
+ "Replacing old symbols for `%s'", 0, 0
+};
+
+struct complaint empty_symtab_complaint = {
+ "Empty symbol table found for `%s'", 0, 0
+};
+
+/* External variables and functions referenced. */
+
+extern int info_verbose;
+
+/* Functions this file defines */
+
+static void
+set_initial_language PARAMS ((void));
+
+static void
+load_command PARAMS ((char *, int));
+
+static void
+add_symbol_file_command PARAMS ((char *, int));
+
+static void
+cashier_psymtab PARAMS ((struct partial_symtab *));
+
+static int
+compare_psymbols PARAMS ((const void *, const void *));
+
+static int
+compare_symbols PARAMS ((const void *, const void *));
+
+static bfd *
+symfile_bfd_open PARAMS ((char *));
+
+static void
+find_sym_fns PARAMS ((struct objfile *));
+
+/* List of all available sym_fns. On gdb startup, each object file reader
+ calls add_symtab_fns() to register information on each format it is
+ prepared to read. */
+
+static struct sym_fns *symtab_fns = NULL;
+
+/* Structures with which to manage partial symbol allocation. */
+
+struct psymbol_allocation_list global_psymbols = {0}, static_psymbols = {0};
+
+/* Flag for whether user will be reloading symbols multiple times.
+ Defaults to ON for VxWorks, otherwise OFF. */
+
+#ifdef SYMBOL_RELOADING_DEFAULT
+int symbol_reloading = SYMBOL_RELOADING_DEFAULT;
+#else
+int symbol_reloading = 0;
+#endif
+
+
+/* Since this function is called from within qsort, in an ANSI environment
+ it must conform to the prototype for qsort, which specifies that the
+ comparison function takes two "void *" pointers. */
+
+static int
+compare_symbols (s1p, s2p)
+ const PTR s1p;
+ const PTR s2p;
+{
+ register struct symbol **s1, **s2;
+
+ s1 = (struct symbol **) s1p;
+ s2 = (struct symbol **) s2p;
+
+ return (STRCMP (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)));
+}
+
+/*
+
+LOCAL FUNCTION
+
+ compare_psymbols -- compare two partial symbols by name
+
+DESCRIPTION
+
+ Given pointer to two partial symbol table entries, compare
+ them by name and return -N, 0, or +N (ala strcmp). Typically
+ used by sorting routines like qsort().
+
+NOTES
+
+ Does direct compare of first two characters before punting
+ and passing to strcmp for longer compares. Note that the
+ original version had a bug whereby two null strings or two
+ identically named one character strings would return the
+ comparison of memory following the null byte.
+
+ */
+
+static int
+compare_psymbols (s1p, s2p)
+ const PTR s1p;
+ const PTR s2p;
+{
+ register char *st1 = SYMBOL_NAME ((struct partial_symbol *) s1p);
+ register char *st2 = SYMBOL_NAME ((struct partial_symbol *) s2p);
+
+ if ((st1[0] - st2[0]) || !st1[0])
+ {
+ return (st1[0] - st2[0]);
+ }
+ else if ((st1[1] - st2[1]) || !st1[1])
+ {
+ return (st1[1] - st2[1]);
+ }
+ else
+ {
+ return (STRCMP (st1 + 2, st2 + 2));
+ }
+}
+
+void
+sort_pst_symbols (pst)
+ struct partial_symtab *pst;
+{
+ /* Sort the global list; don't sort the static list */
+
+ qsort (pst -> objfile -> global_psymbols.list + pst -> globals_offset,
+ pst -> n_global_syms, sizeof (struct partial_symbol),
+ compare_psymbols);
+}
+
+/* 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;
+ int nbl;
+ int i;
+ register struct block *b;
+
+ if (s == 0)
+ return;
+ bv = BLOCKVECTOR (s);
+ nbl = BLOCKVECTOR_NBLOCKS (bv);
+ 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;
+ register struct objfile *objfile;
+
+ for (objfile = object_files; objfile != NULL; objfile = objfile -> next)
+ {
+ for (s = objfile -> symtabs; s != NULL; 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, obstackp)
+ char *ptr;
+ int size;
+ struct obstack *obstackp;
+{
+ register char *p = (char *) obstack_alloc (obstackp, size + 1);
+ /* Open-coded memcpy--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 (obstackp, s1, s2, s3)
+ struct obstack *obstackp;
+ const char *s1, *s2, *s3;
+{
+ register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+ register char *val = (char *) obstack_alloc (obstackp, len);
+ strcpy (val, s1);
+ strcat (val, s2);
+ strcat (val, s3);
+ return val;
+}
+
+/* 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;
+{
+ /* 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);
+ }
+
+ return pst->symtab;
+}
+
+/* Initialize entry point information for this objfile. */
+
+void
+init_entry_point_info (objfile)
+ struct objfile *objfile;
+{
+ /* 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 (objfile -> obfd) & EXEC_P)
+ {
+ /* Executable file -- record its entry point so we'll recognize
+ the startup file because it contains the entry point. */
+ objfile -> ei.entry_point = bfd_get_start_address (objfile -> obfd);
+ }
+ else
+ {
+ /* Examination of non-executable.o files. Short-circuit this stuff. */
+ /* ~0 will not be in any file, we hope. */
+ objfile -> ei.entry_point = ~0;
+ /* set the startup file to be an empty range. */
+ objfile -> ei.entry_file_lowpc = 0;
+ objfile -> ei.entry_file_highpc = 0;
+ }
+}
+
+/* Get current entry point address. */
+
+CORE_ADDR
+entry_point_address()
+{
+ return symfile_objfile ? symfile_objfile->ei.entry_point : 0;
+}
+
+/* Remember the lowest-addressed loadable section we've seen.
+ This function is called via bfd_map_over_sections. */
+
+#if 0 /* Not used yet */
+static void
+find_lowest_section (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ asection **lowest = (asection **)obj;
+
+ if (0 == (bfd_get_section_flags (abfd, sect) & SEC_LOAD))
+ return;
+ if (!*lowest)
+ *lowest = sect; /* First loadable section */
+ else if (bfd_section_vma (abfd, *lowest) >= bfd_section_vma (abfd, sect))
+ *lowest = sect; /* A lower loadable section */
+}
+#endif
+
+/* 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) (but we don't free or modify NAME itself).
+ 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. If VERBO, the caller has printed
+ a verbose message about the symbol reading (and complaints can be
+ more terse about it). */
+
+void
+syms_from_objfile (objfile, addr, mainline, verbo)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+ int mainline;
+ int verbo;
+{
+ struct section_offsets *section_offsets;
+ asection *lowest_sect;
+ struct cleanup *old_chain;
+
+ init_entry_point_info (objfile);
+ find_sym_fns (objfile);
+
+ /* Make sure that partially constructed symbol tables will be cleaned up
+ if an error occurs during symbol reading. */
+ old_chain = make_cleanup (free_objfile, objfile);
+
+ if (mainline)
+ {
+ /* We will modify the main symbol table, make sure that all its users
+ will be cleaned up if an error occurs during symbol reading. */
+ make_cleanup (clear_symtab_users, 0);
+
+ /* Since no error yet, throw away the old symbol table. */
+
+ if (symfile_objfile != NULL)
+ {
+ free_objfile (symfile_objfile);
+ symfile_objfile = NULL;
+ }
+
+ (*objfile -> sf -> sym_new_init) (objfile);
+ }
+
+ /* Convert addr into an offset rather than an absolute address.
+ We find the lowest address of a loaded segment in the objfile,
+ and assume that <addr> is where that got loaded. Due to historical
+ precedent, we warn if that doesn't happen to be the ".text"
+ segment. */
+
+ if (mainline)
+ {
+ addr = 0; /* No offset from objfile addresses. */
+ }
+ else
+ {
+ lowest_sect = bfd_get_section_by_name (objfile->obfd, ".text");
+#if 0
+ lowest_sect = 0;
+ bfd_map_over_sections (objfile->obfd, find_lowest_section,
+ (PTR) &lowest_sect);
+#endif
+
+ if (lowest_sect == 0)
+ warning ("no loadable sections found in added symbol-file %s",
+ objfile->name);
+ else if (0 == bfd_get_section_name (objfile->obfd, lowest_sect)
+ || !STREQ (".text",
+ bfd_get_section_name (objfile->obfd, lowest_sect)))
+ warning ("Lowest section in %s is %s at 0x%lx",
+ objfile->name,
+ bfd_section_name (objfile->obfd, lowest_sect),
+ (unsigned long) bfd_section_vma (objfile->obfd, lowest_sect));
+
+ if (lowest_sect)
+ addr -= bfd_section_vma (objfile->obfd, lowest_sect);
+ }
+
+ /* Initialize symbol reading routines for this objfile, allow complaints to
+ appear for this new file, and record how verbose to be, then do the
+ initial symbol reading for this file. */
+
+ (*objfile -> sf -> sym_init) (objfile);
+ clear_complaints (1, verbo);
+
+ /* If objfile->sf->sym_offsets doesn't set this, we don't care
+ (currently). */
+ objfile->num_sections = 0; /* krp-FIXME: why zero? */
+ section_offsets = (*objfile -> sf -> sym_offsets) (objfile, addr);
+ objfile->section_offsets = section_offsets;
+
+#ifndef IBM6000_TARGET
+ /* This is a SVR4/SunOS specific hack, I think. In any event, it
+ screws RS/6000. sym_offsets should be doing this sort of thing,
+ because it knows the mapping between bfd sections and
+ section_offsets. */
+ /* This is a hack. As far as I can tell, section offsets are not
+ target dependent. They are all set to addr with a couple of
+ exceptions. The exceptions are sysvr4 shared libraries, whose
+ offsets are kept in solib structures anyway and rs6000 xcoff
+ which handles shared libraries in a completely unique way.
+
+ Section offsets are built similarly, except that they are built
+ by adding addr in all cases because there is no clear mapping
+ from section_offsets into actual sections. Note that solib.c
+ has a different algorythm for finding section offsets.
+
+ These should probably all be collapsed into some target
+ independent form of shared library support. FIXME. */
+
+ if (addr)
+ {
+ struct obj_section *s;
+
+ for (s = objfile->sections; s < objfile->sections_end; ++s)
+ {
+ s->addr -= s->offset;
+ s->addr += addr;
+ s->endaddr -= s->offset;
+ s->endaddr += addr;
+ s->offset += addr;
+ }
+ }
+#endif /* not IBM6000_TARGET */
+
+ (*objfile -> sf -> sym_read) (objfile, section_offsets, 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;
+
+ /* Mark the objfile has having had initial symbol read attempted. Note
+ that this does not mean we found any symbols... */
+
+ objfile -> flags |= OBJF_SYMS;
+
+ /* Discard cleanups as symbol reading was successful. */
+
+ discard_cleanups (old_chain);
+}
+
+/* Perform required actions after either reading in the initial
+ symbols for a new objfile, or mapping in the symbols from a reusable
+ objfile. */
+
+void
+new_symfile_objfile (objfile, mainline, verbo)
+ struct objfile *objfile;
+ int mainline;
+ int verbo;
+{
+
+ /* If this is the main symbol file we have to clean up all users of the
+ old main symbol file. Otherwise it is sufficient to fixup all the
+ breakpoints that may have been redefined by this symbol file. */
+ if (mainline)
+ {
+ /* OK, make it the "real" symbol file. */
+ symfile_objfile = objfile;
+
+ clear_symtab_users ();
+ }
+ else
+ {
+ breakpoint_re_set ();
+ }
+
+ /* We're done reading the symbol file; finish off complaints. */
+ clear_complaints (0, verbo);
+}
+
+/* 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) (but we don't free or modify NAME itself).
+ 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.
+
+ Upon success, returns a pointer to the objfile that was added.
+ Upon failure, jumps back to command level (never returns). */
+
+struct objfile *
+symbol_file_add (name, from_tty, addr, mainline, mapped, readnow)
+ char *name;
+ int from_tty;
+ CORE_ADDR addr;
+ int mainline;
+ int mapped;
+ int readnow;
+{
+ struct objfile *objfile;
+ struct partial_symtab *psymtab;
+ bfd *abfd;
+
+ /* Open a bfd for the file, and give user a chance to burp if we'd be
+ interactively wiping out any existing symbols. */
+
+ abfd = symfile_bfd_open (name);
+
+ if ((have_full_symbols () || have_partial_symbols ())
+ && mainline
+ && from_tty
+ && !query ("Load new symbol table from \"%s\"? ", name))
+ error ("Not confirmed.");
+
+ objfile = allocate_objfile (abfd, mapped);
+
+ /* If the objfile uses a mapped symbol file, and we have a psymtab for
+ it, then skip reading any symbols at this time. */
+
+ if ((objfile -> flags & OBJF_MAPPED) && (objfile -> flags & OBJF_SYMS))
+ {
+ /* We mapped in an existing symbol table file that already has had
+ initial symbol reading performed, so we can skip that part. Notify
+ the user that instead of reading the symbols, they have been mapped.
+ */
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("Mapped symbols for %s...", name);
+ wrap_here ("");
+ fflush (stdout);
+ }
+ init_entry_point_info (objfile);
+ find_sym_fns (objfile);
+ }
+ else
+ {
+ /* We either created a new mapped symbol table, mapped an existing
+ symbol table file which has not had initial symbol reading
+ performed, or need to read an unmapped symbol table. */
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("Reading symbols from %s...", name);
+ wrap_here ("");
+ fflush (stdout);
+ }
+ syms_from_objfile (objfile, addr, mainline, from_tty);
+ }
+
+ /* We now have at least a partial symbol table. Check to see if the
+ user requested that all symbols be read on initial access via either
+ the gdb startup command line or on a per symbol file basis. Expand
+ all partial symbol tables for this objfile if so. */
+
+ if (readnow || readnow_symbol_files)
+ {
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("expanding to full symbols...");
+ wrap_here ("");
+ fflush (stdout);
+ }
+
+ for (psymtab = objfile -> psymtabs;
+ psymtab != NULL;
+ psymtab = psymtab -> next)
+ {
+ psymtab_to_symtab (psymtab);
+ }
+ }
+
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("done.\n");
+ fflush (stdout);
+ }
+
+ new_symfile_objfile (objfile, mainline, from_tty);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+
+ reinit_frame_cache ();
+
+ return (objfile);
+}
+
+/* This is the symbol-file command. Read the file, analyze its symbols,
+ and add a struct symtab to a symtab list. */
+
+void
+symbol_file_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ char *name = NULL;
+ struct cleanup *cleanups;
+ int mapped = 0;
+ int readnow = 0;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ if ((have_full_symbols () || have_partial_symbols ())
+ && from_tty
+ && !query ("Discard symbol table from `%s'? ",
+ symfile_objfile -> name))
+ error ("Not confirmed.");
+ free_all_objfiles ();
+ symfile_objfile = NULL;
+ if (from_tty)
+ {
+ printf ("No symbol file now.\n");
+ }
+ }
+ else
+ {
+ if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup (freeargv, (char *) argv);
+ while (*argv != NULL)
+ {
+ if (STREQ (*argv, "-mapped"))
+ {
+ mapped = 1;
+ }
+ else if (STREQ (*argv, "-readnow"))
+ {
+ readnow = 1;
+ }
+ else if (**argv == '-')
+ {
+ error ("unknown option `%s'", *argv);
+ }
+ else
+ {
+ name = *argv;
+ }
+ argv++;
+ }
+
+ if (name == NULL)
+ {
+ error ("no symbol file name was specified");
+ }
+ else
+ {
+ symbol_file_add (name, from_tty, (CORE_ADDR)0, 1, mapped, readnow);
+ set_initial_language ();
+ }
+ do_cleanups (cleanups);
+ }
+}
+
+/* Set the initial language.
+
+ A better solution would be to record the language in the psymtab when reading
+ partial symbols, and then use it (if known) to set the language. This would
+ be a win for formats that encode the language in an easily discoverable place,
+ such as DWARF. For stabs, we can jump through hoops looking for specially
+ named symbols or try to intuit the language from the specific type of stabs
+ we find, but we can't do that until later when we read in full symbols.
+ FIXME. */
+
+static void
+set_initial_language ()
+{
+ struct partial_symtab *pst;
+ enum language lang = language_unknown;
+
+ pst = find_main_psymtab ();
+ if (pst != NULL)
+ {
+ if (pst -> filename != NULL)
+ {
+ lang = deduce_language_from_filename (pst -> filename);
+ }
+ if (lang == language_unknown)
+ {
+ /* Make C the default language */
+ lang = language_c;
+ }
+ set_language (lang);
+ expected_language = current_language; /* Don't warn the user */
+ }
+}
+
+/* Open file specified by NAME and hand it off to BFD for preliminary
+ analysis. Result is a newly initialized bfd *, which includes a newly
+ malloc'd` copy of NAME (tilde-expanded and made absolute).
+ In case of trouble, error() is called. */
+
+static bfd *
+symfile_bfd_open (name)
+ char *name;
+{
+ bfd *sym_bfd;
+ int desc;
+ char *absolute_name;
+
+ name = tilde_expand (name); /* Returns 1st new malloc'd copy */
+
+ /* Look down path for it, allocate 2nd new malloc'd copy. */
+ desc = openp (getenv ("PATH"), 1, name, O_RDONLY | O_BINARY, 0, &absolute_name);
+ if (desc < 0)
+ {
+ make_cleanup (free, name);
+ perror_with_name (name);
+ }
+ free (name); /* Free 1st new malloc'd copy */
+ name = absolute_name; /* Keep 2nd malloc'd copy in bfd */
+ /* It'll be freed in free_objfile(). */
+
+ sym_bfd = bfd_fdopenr (name, gnutarget, desc);
+ if (!sym_bfd)
+ {
+ close (desc);
+ make_cleanup (free, name);
+ error ("\"%s\": can't open to read symbols: %s.", name,
+ bfd_errmsg (bfd_error));
+ }
+ sym_bfd->cacheable = true;
+
+ if (!bfd_check_format (sym_bfd, bfd_object))
+ {
+ bfd_close (sym_bfd); /* This also closes desc */
+ make_cleanup (free, name);
+ 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 on gdb
+ startup by the _initialize routine in each object file format reader,
+ to register information about each format the the reader is prepared
+ to handle. */
+
+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 an initialized struct sym_fns
+ in the objfile structure, that contains cached information about the
+ symbol file. */
+
+static void
+find_sym_fns (objfile)
+ struct objfile *objfile;
+{
+ struct sym_fns *sf;
+
+ for (sf = symtab_fns; sf != NULL; sf = sf -> next)
+ {
+ if (strncmp (bfd_get_target (objfile -> obfd),
+ sf -> sym_name, sf -> sym_namelen) == 0)
+ {
+ objfile -> sf = sf;
+ return;
+ }
+ }
+ error ("I'm sorry, Dave, I can't do that. Symbol format `%s' unknown.",
+ bfd_get_target (objfile -> obfd));
+}
+
+/* This function runs the load command of our current target. */
+
+static void
+load_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ target_load (arg, from_tty);
+}
+
+/* This version of "load" should be usable for any target. Currently
+ it is just used for remote targets, not inftarg.c or core files,
+ on the theory that only in that case is it useful.
+
+ Avoiding xmodem and the like seems like a win (a) because we don't have
+ to worry about finding it, and (b) On VMS, fork() is very slow and so
+ we don't want to run a subprocess. On the other hand, I'm not sure how
+ performance compares. */
+void
+generic_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ struct cleanup *old_cleanups;
+ asection *s;
+ bfd *loadfile_bfd = bfd_openr (filename, gnutarget);
+ if (loadfile_bfd == NULL)
+ {
+ perror_with_name (filename);
+ return;
+ }
+ old_cleanups = make_cleanup (bfd_close, loadfile_bfd);
+
+ if (!bfd_check_format (loadfile_bfd, bfd_object))
+ {
+ error ("\"%s\" is not an object file: %s", filename,
+ bfd_errmsg (bfd_error));
+ }
+
+ for (s = loadfile_bfd->sections; s; s = s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type size;
+
+ size = bfd_get_section_size_before_reloc (s);
+ if (size > 0)
+ {
+ char *buffer;
+ struct cleanup *old_chain;
+ bfd_vma vma;
+
+ buffer = xmalloc (size);
+ old_chain = make_cleanup (free, buffer);
+
+ vma = bfd_get_section_vma (loadfile_bfd, s);
+
+ /* Is this really necessary? I guess it gives the user something
+ to look at during a long download. */
+ printf_filtered ("Loading section %s, size 0x%lx vma 0x%lx\n",
+ bfd_get_section_name (loadfile_bfd, s),
+ (unsigned long) size, (unsigned long) vma);
+
+ bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
+
+ target_write_memory (vma, buffer, size);
+
+ do_cleanups (old_chain);
+ }
+ }
+ }
+
+ /* We were doing this in remote-mips.c, I suspect it is right
+ for other targets too. */
+ write_pc (loadfile_bfd->start_address);
+
+ /* FIXME: are we supposed to call symbol_file_add or not? According to
+ a comment from remote-mips.c (where a call to symbol_file_add was
+ commented out), making the call confuses GDB if more than one file is
+ loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c
+ does. */
+
+ do_cleanups (old_cleanups);
+}
+
+/* This function allows the addition of incrementally linked object files.
+ It does not modify any state in the target, only in the debugger. */
+
+/* ARGSUSED */
+static void
+add_symbol_file_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *name = NULL;
+ CORE_ADDR text_addr;
+ char *arg;
+ int readnow = 0;
+ int mapped = 0;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("add-symbol-file takes a file name and an address");
+ }
+
+ /* Make a copy of the string that we can safely write into. */
+
+ args = strdup (args);
+ make_cleanup (free, args);
+
+ /* Pick off any -option args and the file name. */
+
+ while ((*args != '\000') && (name == NULL))
+ {
+ while (isspace (*args)) {args++;}
+ arg = args;
+ while ((*args != '\000') && !isspace (*args)) {args++;}
+ if (*args != '\000')
+ {
+ *args++ = '\000';
+ }
+ if (*arg != '-')
+ {
+ name = arg;
+ }
+ else if (STREQ (arg, "-mapped"))
+ {
+ mapped = 1;
+ }
+ else if (STREQ (arg, "-readnow"))
+ {
+ readnow = 1;
+ }
+ else
+ {
+ error ("unknown option `%s'", arg);
+ }
+ }
+
+ /* After picking off any options and the file name, args should be
+ left pointing at the remainder of the command line, which should
+ be the address expression to evaluate. */
+
+ if ((name == NULL) || (*args == '\000') )
+ {
+ error ("add-symbol-file takes a file name and an address");
+ }
+ name = tilde_expand (name);
+ make_cleanup (free, name);
+
+ text_addr = parse_and_eval_address (args);
+
+ if (!query ("add symbol table from file \"%s\" at text_addr = %s?\n",
+ name, local_hex_string ((unsigned long)text_addr)))
+ error ("Not confirmed.");
+
+ symbol_file_add (name, 0, text_addr, 0, mapped, readnow);
+}
+
+/* Re-read symbols if a symbol-file has changed. */
+void
+reread_symbols ()
+{
+ struct objfile *objfile;
+ long new_modtime;
+ int reread_one = 0;
+ struct stat new_statbuf;
+ int res;
+
+ /* 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 */
+
+the_big_top:
+ for (objfile = object_files; objfile; objfile = objfile->next) {
+ if (objfile->obfd) {
+#ifdef IBM6000_TARGET
+ /* If this object is from a shared library, then you should
+ stat on the library name, not member name. */
+
+ if (objfile->obfd->my_archive)
+ res = stat (objfile->obfd->my_archive->filename, &new_statbuf);
+ else
+#endif
+ res = stat (objfile->name, &new_statbuf);
+ if (res != 0) {
+ /* FIXME, should use print_sys_errmsg but it's not filtered. */
+ printf_filtered ("`%s' has disappeared; keeping its symbols.\n",
+ objfile->name);
+ continue;
+ }
+ new_modtime = new_statbuf.st_mtime;
+ if (new_modtime != objfile->mtime) {
+ printf_filtered ("`%s' has changed; re-reading symbols.\n",
+ objfile->name);
+ /* FIXME, this should use a different command...that would only
+ affect this objfile's symbols, and would reset objfile->mtime.
+ (objfile->mtime = new_modtime;)
+ HOWEVER, that command isn't written yet -- so call symbol_file_
+ command, and restart the scan from the top, because it munges
+ the object_files list. */
+ symbol_file_command (objfile->name, 0);
+ reread_one = 1;
+ goto the_big_top; /* Start over. */
+ }
+ }
+ }
+
+ if (reread_one)
+ breakpoint_re_set ();
+}
+
+
+enum language
+deduce_language_from_filename (filename)
+ char *filename;
+{
+ char *c;
+
+ if (0 == filename)
+ ; /* Get default */
+ else if (0 == (c = strrchr (filename, '.')))
+ ; /* Get default. */
+ else if (STREQ(c,".mod"))
+ return language_m2;
+ else if (STREQ(c,".c"))
+ return language_c;
+ else if (STREQ (c,".cc") || STREQ (c,".C") || STREQ (c, ".cxx"))
+ return language_cplus;
+ else if (STREQ (c,".ch") || STREQ (c,".c186") || STREQ (c,".c286"))
+ return language_chill;
+
+ return language_unknown; /* default */
+}
+
+/* allocate_symtab:
+
+ Allocate and partly initialize a new symbol table. Return a pointer
+ to it. error() if no space.
+
+ Caller must set these fields:
+ LINETABLE(symtab)
+ symtab->blockvector
+ symtab->dirname
+ symtab->free_code
+ symtab->free_ptr
+ initialize any EXTRA_SYMTAB_INFO
+ possibly free_named_symtabs (symtab->filename);
+ */
+
+struct symtab *
+allocate_symtab (filename, objfile)
+ char *filename;
+ struct objfile *objfile;
+{
+ register struct symtab *symtab;
+
+ symtab = (struct symtab *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symtab));
+ memset (symtab, 0, sizeof (*symtab));
+ symtab -> filename = obsavestring (filename, strlen (filename),
+ &objfile -> symbol_obstack);
+ symtab -> fullname = NULL;
+ symtab -> language = deduce_language_from_filename (filename);
+
+ /* Hook it to the objfile it comes from */
+
+ symtab -> objfile = objfile;
+ symtab -> next = objfile -> symtabs;
+ objfile -> symtabs = symtab;
+
+#ifdef INIT_EXTRA_SYMTAB_INFO
+ INIT_EXTRA_SYMTAB_INFO (symtab);
+#endif
+
+ return (symtab);
+}
+
+struct partial_symtab *
+allocate_psymtab (filename, objfile)
+ char *filename;
+ struct objfile *objfile;
+{
+ struct partial_symtab *psymtab;
+
+ if (objfile -> free_psymtabs)
+ {
+ psymtab = objfile -> free_psymtabs;
+ objfile -> free_psymtabs = psymtab -> next;
+ }
+ else
+ psymtab = (struct partial_symtab *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct partial_symtab));
+
+ memset (psymtab, 0, sizeof (struct partial_symtab));
+ psymtab -> filename = obsavestring (filename, strlen (filename),
+ &objfile -> psymbol_obstack);
+ psymtab -> symtab = NULL;
+
+ /* Hook it to the objfile it comes from */
+
+ psymtab -> objfile = objfile;
+ psymtab -> next = objfile -> psymtabs;
+ objfile -> psymtabs = psymtab;
+
+ return (psymtab);
+}
+
+
+/* Reset all data structures in gdb which may contain references to symbol
+ table date. */
+
+void
+clear_symtab_users ()
+{
+ /* Someday, we should do better than this, by only blowing away
+ the things that really need to be blown. */
+ clear_value_history ();
+ clear_displays ();
+ clear_internalvars ();
+ breakpoint_re_set ();
+ set_default_breakpoint (0, 0, 0, 0);
+ current_source_symtab = 0;
+ current_source_line = 0;
+}
+
+/* clear_symtab_users_once:
+
+ This function is run after symbol reading, or from a cleanup.
+ If an old symbol table was obsoleted, the old symbol table
+ has been blown away, but the other GDB data structures that may
+ reference it have not yet been cleared or re-directed. (The old
+ symtab was zapped, and the cleanup queued, in free_named_symtab()
+ below.)
+
+ This function can be queued N times as a cleanup, or called
+ directly; it will do all the work the first time, and then will be a
+ no-op until the next time it is queued. This works by bumping a
+ counter at queueing time. Much later when the cleanup is run, or at
+ the end of symbol processing (in case the cleanup is discarded), if
+ the queued count is greater than the "done-count", we do the work
+ and set the done-count to the queued count. If the queued count is
+ less than or equal to the done-count, we just ignore the call. This
+ is needed because reading a single .o file will often replace many
+ symtabs (one per .h file, for example), and we don't want to reset
+ the breakpoints N times in the user's face.
+
+ The reason we both queue a cleanup, and call it directly after symbol
+ reading, is because the cleanup protects us in case of errors, but is
+ discarded if symbol reading is successful. */
+
+#if 0
+/* FIXME: As free_named_symtabs is currently a big noop this function
+ is no longer needed. */
+static void
+clear_symtab_users_once PARAMS ((void));
+
+static int clear_symtab_users_queued;
+static int clear_symtab_users_done;
+
+static void
+clear_symtab_users_once ()
+{
+ /* Enforce once-per-`do_cleanups'-semantics */
+ if (clear_symtab_users_queued <= clear_symtab_users_done)
+ return;
+ clear_symtab_users_done = clear_symtab_users_queued;
+
+ clear_symtab_users ();
+}
+#endif
+
+/* Delete the specified psymtab, and any others that reference it. */
+
+static void
+cashier_psymtab (pst)
+ struct partial_symtab *pst;
+{
+ struct partial_symtab *ps, *pprev = NULL;
+ int i;
+
+ /* Find its previous psymtab in the chain */
+ for (ps = pst->objfile->psymtabs; ps; ps = ps->next) {
+ if (ps == pst)
+ break;
+ pprev = ps;
+ }
+
+ if (ps) {
+ /* Unhook it from the chain. */
+ if (ps == pst->objfile->psymtabs)
+ pst->objfile->psymtabs = ps->next;
+ else
+ pprev->next = ps->next;
+
+ /* FIXME, we can't conveniently deallocate the entries in the
+ partial_symbol lists (global_psymbols/static_psymbols) that
+ this psymtab points to. These just take up space until all
+ the psymtabs are reclaimed. Ditto the dependencies list and
+ filename, which are all in the psymbol_obstack. */
+
+ /* We need to cashier any psymtab that has this one as a dependency... */
+again:
+ for (ps = pst->objfile->psymtabs; ps; ps = ps->next) {
+ for (i = 0; i < ps->number_of_dependencies; i++) {
+ if (ps->dependencies[i] == pst) {
+ cashier_psymtab (ps);
+ goto again; /* Must restart, chain has been munged. */
+ }
+ }
+ }
+ }
+}
+
+/* If a symtab or psymtab 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. This is only called on the top-level symtab or psymtab's name;
+ it is not called for subsidiary files such as .h files.
+
+ Return value is 1 if we blew away the environment, 0 if not.
+ FIXME. The return valu appears to never be used.
+
+ FIXME. I think this is not the best way to do this. We should
+ work on being gentler to the environment while still cleaning up
+ all stray pointers into the freed symtab. */
+
+int
+free_named_symtabs (name)
+ char *name;
+{
+#if 0
+ /* FIXME: With the new method of each objfile having it's own
+ psymtab list, this function needs serious rethinking. In particular,
+ why was it ever necessary to toss psymtabs with specific compilation
+ unit filenames, as opposed to all psymtabs from a particular symbol
+ file? -- fnf
+ Well, the answer is that some systems permit reloading of particular
+ compilation units. We want to blow away any old info about these
+ compilation units, regardless of which objfiles they arrived in. --gnu. */
+
+ register struct symtab *s;
+ register struct symtab *prev;
+ register struct partial_symtab *ps;
+ struct blockvector *bv;
+ int blewit = 0;
+
+ /* We only wack things if the symbol-reload switch is set. */
+ if (!symbol_reloading)
+ return 0;
+
+ /* Some symbol formats have trouble providing file names... */
+ if (name == 0 || *name == '\0')
+ return 0;
+
+ /* Look for a psymtab with the specified name. */
+
+again2:
+ for (ps = partial_symtab_list; ps; ps = ps->next) {
+ if (STREQ (name, ps->filename)) {
+ cashier_psymtab (ps); /* Blow it away...and its little dog, too. */
+ goto again2; /* Must restart, chain has been munged */
+ }
+ }
+
+ /* Look for a symtab with the specified name. */
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ if (STREQ (name, s->filename))
+ break;
+ prev = s;
+ }
+
+ if (s)
+ {
+ if (s == symtab_list)
+ symtab_list = s->next;
+ else
+ prev->next = s->next;
+
+ /* For now, queue a delete for 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 = BLOCKVECTOR (s);
+ if (BLOCKVECTOR_NBLOCKS (bv) > 2
+ || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK))
+ || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)))
+ {
+ complain (&oldsyms_complaint, name);
+
+ clear_symtab_users_queued++;
+ make_cleanup (clear_symtab_users_once, 0);
+ blewit = 1;
+ } else {
+ complain (&empty_symtab_complaint, name);
+ }
+
+ 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. */
+ ;
+ }
+
+ /* FIXME, what about the minimal symbol table? */
+ return blewit;
+#else
+ return (0);
+#endif
+}
+
+/* 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). */
+
+
+struct partial_symtab *
+start_psymtab_common (objfile, section_offsets,
+ filename, textlow, global_syms, static_syms)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ char *filename;
+ CORE_ADDR textlow;
+ struct partial_symbol *global_syms;
+ struct partial_symbol *static_syms;
+{
+ struct partial_symtab *psymtab;
+
+ psymtab = allocate_psymtab (filename, objfile);
+ psymtab -> section_offsets = section_offsets;
+ psymtab -> textlow = textlow;
+ psymtab -> texthigh = psymtab -> textlow; /* default */
+ psymtab -> globals_offset = global_syms - objfile -> global_psymbols.list;
+ psymtab -> statics_offset = static_syms - objfile -> static_psymbols.list;
+ return (psymtab);
+}
+
+/* Debugging versions of functions that are usually inline macros
+ (see symfile.h). */
+
+#if !INLINE_ADD_PSYMBOL
+
+/* Add a symbol with a long value to a psymtab.
+ Since one arg is a struct, we pass in a ptr and deref it (sigh). */
+
+void
+add_psymbol_to_list (name, namelength, namespace, class, list, val, language,
+ objfile)
+ char *name;
+ int namelength;
+ enum namespace namespace;
+ enum address_class class;
+ struct psymbol_allocation_list *list;
+ long val;
+ enum language language;
+ struct objfile *objfile;
+{
+ register struct partial_symbol *psym;
+ register char *demangled_name;
+
+ if (list->next >= list->list + list->size)
+ {
+ extend_psymbol_list (list,objfile);
+ }
+ psym = list->next++;
+
+ SYMBOL_NAME (psym) =
+ (char *) obstack_alloc (&objfile->psymbol_obstack, namelength + 1);
+ memcpy (SYMBOL_NAME (psym), name, namelength);
+ SYMBOL_NAME (psym)[namelength] = '\0';
+ SYMBOL_VALUE (psym) = val;
+ SYMBOL_LANGUAGE (psym) = language;
+ PSYMBOL_NAMESPACE (psym) = namespace;
+ PSYMBOL_CLASS (psym) = class;
+ SYMBOL_INIT_DEMANGLED_NAME (psym, &objfile->psymbol_obstack);
+}
+
+/* Add a symbol with a CORE_ADDR value to a psymtab. */
+
+void
+add_psymbol_addr_to_list (name, namelength, namespace, class, list, val,
+ language, objfile)
+ char *name;
+ int namelength;
+ enum namespace namespace;
+ enum address_class class;
+ struct psymbol_allocation_list *list;
+ CORE_ADDR val;
+ enum language language;
+ struct objfile *objfile;
+{
+ register struct partial_symbol *psym;
+ register char *demangled_name;
+
+ if (list->next >= list->list + list->size)
+ {
+ extend_psymbol_list (list,objfile);
+ }
+ psym = list->next++;
+
+ SYMBOL_NAME (psym) =
+ (char *) obstack_alloc (&objfile->psymbol_obstack, namelength + 1);
+ memcpy (SYMBOL_NAME (psym), name, namelength);
+ SYMBOL_NAME (psym)[namelength] = '\0';
+ SYMBOL_VALUE_ADDRESS (psym) = val;
+ SYMBOL_LANGUAGE (psym) = language;
+ PSYMBOL_NAMESPACE (psym) = namespace;
+ PSYMBOL_CLASS (psym) = class;
+ SYMBOL_INIT_DEMANGLED_NAME (psym, &objfile->psymbol_obstack);
+}
+
+#endif /* !INLINE_ADD_PSYMBOL */
+
+
+void
+_initialize_symfile ()
+{
+ struct cmd_list_element *c;
+
+ c = add_cmd ("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.", &cmdlist);
+ c->completer = filename_completer;
+
+ c = add_cmd ("add-symbol-file", class_files, add_symbol_file_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.",
+ &cmdlist);
+ c->completer = filename_completer;
+
+ c = add_cmd ("load", class_files, load_command,
+ "Dynamically load FILE into the running program, and record its symbols\n\
+for access from GDB.", &cmdlist);
+ c->completer = filename_completer;
+
+ add_show_from_set
+ (add_set_cmd ("symbol-reloading", class_support, var_boolean,
+ (char *)&symbol_reloading,
+ "Set dynamic symbol table reloading multiple times in one run.",
+ &setlist),
+ &showlist);
+
+}
diff --git a/gnu/usr.bin/gdb/gdb/symfile.h b/gnu/usr.bin/gdb/gdb/symfile.h
new file mode 100644
index 000000000000..70bc73db4b00
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/symfile.h
@@ -0,0 +1,228 @@
+/* Definitions for reading symbol files into GDB.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (SYMFILE_H)
+#define SYMFILE_H
+
+/* This file requires that you first include "bfd.h". */
+
+struct psymbol_allocation_list {
+ struct partial_symbol *list;
+ struct partial_symbol *next;
+ int size;
+};
+
+/* Structure to keep track of symbol reading functions for various
+ object file types. */
+
+struct sym_fns {
+
+ /* 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" or "elf". */
+
+ char *sym_name;
+
+ /* 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 '\0'. If a prefix match is desired, specify the number of
+ characters in sym_name. */
+
+ int sym_namelen;
+
+ /* Initializes anything that is global to the entire symbol table. It is
+ called during symbol_file_add, when we begin debugging an entirely new
+ program. */
+
+ void (*sym_new_init) PARAMS ((struct objfile *));
+
+ /* 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) PARAMS ((struct objfile *));
+
+ /* sym_read (objfile, addr, mainline)
+ Reads a symbol file into a psymtab (or possibly a symtab).
+ OBJFILE is the objfile struct for the file we are reading.
+ SECTION_OFFSETS
+ are the offset between the file's specified section addresses and
+ their true addresses 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) PARAMS ((struct objfile *, struct section_offsets *, int));
+
+ /* Called when we are finished with an objfile. Should do all cleanup
+ that is specific to the object file format for the particular objfile. */
+
+ void (*sym_finish) PARAMS ((struct objfile *));
+
+ /* This function produces a file-dependent section_offsets structure,
+ allocated in the objfile's storage, and based on the parameter.
+ The parameter is currently a CORE_ADDR (FIXME!) for backward compatibility
+ with the higher levels of GDB. It should probably be changed to
+ a string, where NULL means the default, and others are parsed in a file
+ dependent way. The result of this function is handed in to sym_read. */
+
+ struct section_offsets *(*sym_offsets) PARAMS ((struct objfile *, CORE_ADDR));
+
+ /* 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;
+
+};
+
+extern void
+extend_psymbol_list PARAMS ((struct psymbol_allocation_list *,
+ struct objfile *));
+
+/* Add any kind of symbol to a psymbol_allocation_list. */
+
+#ifndef INLINE_ADD_PSYMBOL
+#define INLINE_ADD_PSYMBOL 1
+#endif
+
+#if !INLINE_ADD_PSYMBOL
+
+/* 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, language, objfile) \
+ add_psymbol_to_list (name, namelength, namespace, class, &list, value, language, objfile)
+
+#define ADD_PSYMBOL_ADDR_TO_LIST(name, namelength, namespace, class, list, value, language, objfile) \
+ add_psymbol_addr_to_list (name, namelength, namespace, class, &list, value, language, objfile)
+
+#else /* !INLINE_ADD_PSYMBOL */
+
+#include "demangle.h"
+
+#define ADD_PSYMBOL_VT_TO_LIST(NAME,NAMELENGTH,NAMESPACE,CLASS,LIST,VALUE,VT,LANGUAGE, OBJFILE) \
+ do { \
+ register struct partial_symbol *psym; \
+ if ((LIST).next >= (LIST).list + (LIST).size) \
+ extend_psymbol_list (&(LIST),(OBJFILE)); \
+ psym = (LIST).next++; \
+ SYMBOL_NAME (psym) = \
+ (char *) obstack_alloc (&objfile->psymbol_obstack, \
+ (NAMELENGTH) + 1); \
+ memcpy (SYMBOL_NAME (psym), (NAME), (NAMELENGTH)); \
+ SYMBOL_NAME (psym)[(NAMELENGTH)] = '\0'; \
+ SYMBOL_NAMESPACE (psym) = (NAMESPACE); \
+ PSYMBOL_CLASS (psym) = (CLASS); \
+ VT (psym) = (VALUE); \
+ SYMBOL_LANGUAGE (psym) = (LANGUAGE); \
+ SYMBOL_INIT_DEMANGLED_NAME (psym, &objfile->psymbol_obstack); \
+ } while (0);
+
+/* Add a symbol with an integer value to a psymtab. */
+
+#define ADD_PSYMBOL_TO_LIST(name, namelength, namespace, class, list, value, language, objfile) \
+ ADD_PSYMBOL_VT_TO_LIST (name, namelength, namespace, class, list, value, SYMBOL_VALUE, language, objfile)
+
+/* Add a symbol with a CORE_ADDR value to a psymtab. */
+
+#define ADD_PSYMBOL_ADDR_TO_LIST(name, namelength, namespace, class, list, value, language, objfile)\
+ ADD_PSYMBOL_VT_TO_LIST (name, namelength, namespace, class, list, value, SYMBOL_VALUE_ADDRESS, language, objfile)
+
+#endif /* INLINE_ADD_PSYMBOL */
+
+ /* Functions */
+
+extern void
+sort_pst_symbols PARAMS ((struct partial_symtab *));
+
+extern struct symtab *
+allocate_symtab PARAMS ((char *, struct objfile *));
+
+extern int
+free_named_symtabs PARAMS ((char *));
+
+extern void
+fill_in_vptr_fieldno PARAMS ((struct type *));
+
+extern void
+add_symtab_fns PARAMS ((struct sym_fns *));
+
+extern void
+init_entry_point_info PARAMS ((struct objfile *));
+
+extern void
+syms_from_objfile PARAMS ((struct objfile *, CORE_ADDR, int, int));
+
+extern void
+new_symfile_objfile PARAMS ((struct objfile *, int, int));
+
+extern struct partial_symtab *
+start_psymtab_common PARAMS ((struct objfile *, struct section_offsets *,
+ char *, CORE_ADDR,
+ struct partial_symbol *,
+ struct partial_symbol *));
+
+/* Sorting your symbols for fast lookup or alphabetical printing. */
+
+extern void
+sort_block_syms PARAMS ((struct block *));
+
+extern void
+sort_symtab_syms PARAMS ((struct symtab *));
+
+extern void
+sort_all_symtab_syms PARAMS ((void));
+
+/* 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 PARAMS ((char *, int, struct obstack *));
+
+/* Concatenate strings S1, S2 and S3; return the new string.
+ Space is found in the symbol_obstack. */
+
+extern char *
+obconcat PARAMS ((struct obstack *obstackp, const char *, const char *,
+ const char *));
+
+ /* Variables */
+
+/* From symfile.c */
+
+extern struct partial_symtab *
+allocate_psymtab PARAMS ((char *, struct objfile *));
+
+/* Remote targets may wish to use this as their load function. */
+extern void generic_load PARAMS ((char *name, int from_tty));
+
+/* From dwarfread.c */
+
+extern void
+dwarf_build_psymtabs PARAMS ((struct objfile *, struct section_offsets *, int,
+ file_ptr, unsigned int, file_ptr, unsigned int));
+
+/* From demangle.c */
+
+extern void
+set_demangling_style PARAMS ((char *));
+
+#endif /* !defined(SYMFILE_H) */
diff --git a/gnu/usr.bin/gdb/gdb/symmisc.c b/gnu/usr.bin/gdb/gdb/symmisc.c
new file mode 100644
index 000000000000..411a53bef96a
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/symmisc.c
@@ -0,0 +1,857 @@
+/* Do various things to symbol tables (other than lookup), for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "breakpoint.h"
+#include "command.h"
+#include "obstack.h"
+#include "language.h"
+
+#include <string.h>
+
+#ifndef DEV_TTY
+#define DEV_TTY "/dev/tty"
+#endif
+
+/* Unfortunately for debugging, stderr is usually a macro. This is painful
+ when calling functions that take FILE *'s from the debugger.
+ So we make a variable which has the same value and which is accessible when
+ debugging GDB with itself. Because stdin et al need not be constants,
+ we initialize them in the _initialize_symmisc function at the bottom
+ of the file. */
+FILE *std_in;
+FILE *std_out;
+FILE *std_err;
+
+/* Prototypes for local functions */
+
+static void
+dump_symtab PARAMS ((struct objfile *, struct symtab *, FILE *));
+
+static void
+dump_psymtab PARAMS ((struct objfile *, struct partial_symtab *, FILE *));
+
+static void
+dump_msymbols PARAMS ((struct objfile *, FILE *));
+
+static void
+dump_objfile PARAMS ((struct objfile *));
+
+static int
+block_depth PARAMS ((struct block *));
+
+static void
+print_partial_symbol PARAMS ((struct partial_symbol *, int, char *, FILE *));
+
+struct print_symbol_args {
+ struct symbol *symbol;
+ int depth;
+ FILE *outfile;
+};
+
+static int print_symbol PARAMS ((char *));
+
+static void
+free_symtab_block PARAMS ((struct objfile *, struct block *));
+
+
+/* Free a struct block <- B and all the symbols defined in that block. */
+
+static void
+free_symtab_block (objfile, b)
+ struct objfile *objfile;
+ struct block *b;
+{
+ register int i, n;
+ n = BLOCK_NSYMS (b);
+ for (i = 0; i < n; i++)
+ {
+ mfree (objfile -> md, SYMBOL_NAME (BLOCK_SYM (b, i)));
+ mfree (objfile -> md, (PTR) BLOCK_SYM (b, i));
+ }
+ mfree (objfile -> md, (PTR) 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. */
+
+void
+free_symtab (s)
+ register struct symtab *s;
+{
+ register int i, n;
+ register struct blockvector *bv;
+
+ switch (s->free_code)
+ {
+ case free_nothing:
+ /* All the contents are part of a big block of memory (an obstack),
+ 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 (s -> objfile, BLOCKVECTOR_BLOCK (bv, i));
+ /* Free the blockvector itself. */
+ mfree (s -> objfile -> md, (PTR) bv);
+ /* Also free the linetable. */
+
+ case free_linetable:
+ /* Everything will be freed either by our `free_ptr'
+ or by some other symtab, except for our linetable.
+ Free that now. */
+ if (LINETABLE (s))
+ mfree (s -> objfile -> md, (PTR) LINETABLE (s));
+ break;
+ }
+
+ /* If there is a single block of memory to free, free it. */
+ if (s -> free_ptr != NULL)
+ mfree (s -> objfile -> md, s -> free_ptr);
+
+ /* Free source-related stuff */
+ if (s -> line_charpos != NULL)
+ mfree (s -> objfile -> md, (PTR) s -> line_charpos);
+ if (s -> fullname != NULL)
+ mfree (s -> objfile -> md, s -> fullname);
+ mfree (s -> objfile -> md, (PTR) s);
+}
+
+#if MAINTENANCE_CMDS
+
+static void
+dump_objfile (objfile)
+ struct objfile *objfile;
+{
+ struct symtab *symtab;
+ struct partial_symtab *psymtab;
+
+ printf_filtered ("\nObject file %s: ", objfile -> name);
+ printf_filtered ("Objfile at %lx, bfd at %lx, %d minsyms\n\n",
+ (unsigned long) objfile,
+ (unsigned long) objfile -> obfd,
+ objfile->minimal_symbol_count);
+
+ if (objfile -> psymtabs)
+ {
+ printf_filtered ("Psymtabs:\n");
+ for (psymtab = objfile -> psymtabs;
+ psymtab != NULL;
+ psymtab = psymtab -> next)
+ {
+ printf_filtered ("%s at %lx, ",
+ psymtab -> filename, (unsigned long) psymtab);
+ if (psymtab -> objfile != objfile)
+ {
+ printf_filtered ("NOT ON CHAIN! ");
+ }
+ wrap_here (" ");
+ }
+ printf_filtered ("\n\n");
+ }
+
+ if (objfile -> symtabs)
+ {
+ printf_filtered ("Symtabs:\n");
+ for (symtab = objfile -> symtabs;
+ symtab != NULL;
+ symtab = symtab->next)
+ {
+ printf_filtered ("%s at %lx, ",
+ symtab -> filename, (unsigned long) symtab);
+ if (symtab -> objfile != objfile)
+ {
+ printf_filtered ("NOT ON CHAIN! ");
+ }
+ wrap_here (" ");
+ }
+ printf_filtered ("\n\n");
+ }
+}
+
+/* Print minimal symbols from this objfile. */
+
+static void
+dump_msymbols (objfile, outfile)
+ struct objfile *objfile;
+ FILE *outfile;
+{
+ struct minimal_symbol *msymbol;
+ int index;
+ char ms_type;
+
+ fprintf_filtered (outfile, "\nObject file %s:\n\n", objfile -> name);
+ if (objfile -> minimal_symbol_count == 0)
+ {
+ fprintf_filtered (outfile, "No minimal symbols found.\n");
+ return;
+ }
+ for (index = 0, msymbol = objfile -> msymbols;
+ SYMBOL_NAME (msymbol) != NULL; msymbol++, index++)
+ {
+ switch (msymbol -> type)
+ {
+ case mst_unknown:
+ ms_type = 'u';
+ break;
+ case mst_text:
+ ms_type = 'T';
+ break;
+ case mst_data:
+ ms_type = 'D';
+ break;
+ case mst_bss:
+ ms_type = 'B';
+ break;
+ case mst_abs:
+ ms_type = 'A';
+ break;
+ case mst_file_text:
+ ms_type = 't';
+ break;
+ case mst_file_data:
+ ms_type = 'd';
+ break;
+ case mst_file_bss:
+ ms_type = 'b';
+ break;
+ default:
+ ms_type = '?';
+ break;
+ }
+ fprintf_filtered (outfile, "[%2d] %c %#10lx %s", index, ms_type,
+ SYMBOL_VALUE_ADDRESS (msymbol), SYMBOL_NAME (msymbol));
+ if (SYMBOL_DEMANGLED_NAME (msymbol) != NULL)
+ {
+ fprintf_filtered (outfile, " %s", SYMBOL_DEMANGLED_NAME (msymbol));
+ }
+ fputs_filtered ("\n", outfile);
+ }
+ if (objfile -> minimal_symbol_count != index)
+ {
+ warning ("internal error: minimal symbol count %d != %d",
+ objfile -> minimal_symbol_count, index);
+ }
+ fprintf_filtered (outfile, "\n");
+}
+
+static void
+dump_psymtab (objfile, psymtab, outfile)
+ struct objfile *objfile;
+ struct partial_symtab *psymtab;
+ FILE *outfile;
+{
+ int i;
+
+ fprintf_filtered (outfile, "\nPartial symtab for source file %s ",
+ psymtab -> filename);
+ fprintf_filtered (outfile, "(object 0x%lx)\n\n", (unsigned long) psymtab);
+ fprintf (outfile, " Read from object file %s (0x%lx)\n",
+ objfile -> name, (unsigned long) objfile);
+
+ if (psymtab -> readin)
+ {
+ fprintf_filtered (outfile,
+ " Full symtab was read (at 0x%lx by function at 0x%lx)\n",
+ (unsigned long) psymtab -> symtab,
+ (unsigned long) psymtab -> read_symtab);
+ }
+
+ /* FIXME, we need to be able to print the relocation stuff. */
+ /* This prints some garbage for anything but stabs right now. FIXME. */
+ if (psymtab->section_offsets)
+ fprintf_filtered (outfile,
+ " Relocate symbols by 0x%lx, 0x%lx, 0x%lx, 0x%lx.\n",
+ (unsigned long) ANOFFSET (psymtab->section_offsets, 0),
+ (unsigned long) ANOFFSET (psymtab->section_offsets, 1),
+ (unsigned long) ANOFFSET (psymtab->section_offsets, 2),
+ (unsigned long) ANOFFSET (psymtab->section_offsets, 3));
+
+ fprintf_filtered (outfile, " Symbols cover text addresses 0x%lx-0x%lx\n",
+ (unsigned long) psymtab -> textlow,
+ (unsigned long) psymtab -> texthigh);
+ fprintf_filtered (outfile, " Depends on %d other partial symtabs.\n",
+ psymtab -> number_of_dependencies);
+ for (i = 0; i < psymtab -> number_of_dependencies; i++)
+ {
+ fprintf_filtered (outfile, " %d 0x%lx %s\n", i,
+ (unsigned long) psymtab -> dependencies[i],
+ psymtab -> dependencies[i] -> filename);
+ }
+ if (psymtab -> n_global_syms > 0)
+ {
+ print_partial_symbol (objfile -> global_psymbols.list
+ + psymtab -> globals_offset,
+ psymtab -> n_global_syms, "Global", outfile);
+ }
+ if (psymtab -> n_static_syms > 0)
+ {
+ print_partial_symbol (objfile -> static_psymbols.list
+ + psymtab -> statics_offset,
+ psymtab -> n_static_syms, "Static", outfile);
+ }
+ fprintf_filtered (outfile, "\n");
+}
+
+static void
+dump_symtab (objfile, symtab, outfile)
+ struct objfile *objfile;
+ struct symtab *symtab;
+ FILE *outfile;
+{
+ register int i, j;
+ int len, blen;
+ register struct linetable *l;
+ struct blockvector *bv;
+ register struct block *b;
+ int depth;
+
+ fprintf (outfile, "\nSymtab for file %s\n", symtab->filename);
+ fprintf (outfile, "Read from object file %s (%lx)\n", objfile->name,
+ (unsigned long) objfile);
+ fprintf (outfile, "Language: %s\n", language_str (symtab -> language));
+
+ /* First print the line table. */
+ l = LINETABLE (symtab);
+ if (l) {
+ fprintf (outfile, "\nLine table:\n\n");
+ len = l->nitems;
+ for (i = 0; i < len; i++)
+ fprintf (outfile, " line %ld at %lx\n", l->item[i].line,
+ (unsigned long) l->item[i].pc);
+ }
+ /* Now print the block info. */
+ fprintf (outfile, "\nBlockvector:\n\n");
+ bv = BLOCKVECTOR (symtab);
+ 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%lx) ", i, (unsigned long) b);
+ fprintf (outfile, "[0x%lx..0x%lx]",
+ (unsigned long) BLOCK_START (b),
+ (unsigned long) BLOCK_END (b));
+ if (BLOCK_SUPERBLOCK (b))
+ fprintf (outfile, " (under 0x%lx)",
+ (unsigned long) BLOCK_SUPERBLOCK (b));
+ if (BLOCK_FUNCTION (b))
+ {
+ fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
+ if (SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)) != NULL)
+ {
+ fprintf (outfile, " %s",
+ SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)));
+ }
+ }
+ if (BLOCK_GCC_COMPILED(b))
+ fprintf (outfile, " gcc%d compiled", BLOCK_GCC_COMPILED(b));
+ fputc ('\n', outfile);
+ blen = BLOCK_NSYMS (b);
+ for (j = 0; j < blen; j++)
+ {
+ struct print_symbol_args s;
+ s.symbol = BLOCK_SYM (b, j);
+ s.depth = depth + 1;
+ s.outfile = outfile;
+ catch_errors (print_symbol, &s, "Error printing symbol:\n",
+ RETURN_MASK_ERROR);
+ }
+ }
+ fprintf (outfile, "\n");
+}
+
+void
+maintenance_print_symbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ FILE *outfile;
+ struct cleanup *cleanups;
+ char *symname = NULL;
+ char *filename = DEV_TTY;
+ struct objfile *objfile;
+ struct symtab *s;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("print-symbols takes an output file name and optional symbol file name");
+ }
+ else if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup (freeargv, (char *) argv);
+
+ if (argv[0] != NULL)
+ {
+ filename = argv[0];
+ /* If a second arg is supplied, it is a source file name to match on */
+ if (argv[1] != NULL)
+ {
+ symname = argv[1];
+ }
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ outfile = fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup (fclose, (char *) outfile);
+
+ immediate_quit++;
+ ALL_SYMTABS (objfile, s)
+ if (symname == NULL || (STREQ (symname, s -> filename)))
+ dump_symtab (objfile, s, outfile);
+ immediate_quit--;
+ do_cleanups (cleanups);
+}
+
+/* Print symbol ARGS->SYMBOL on ARGS->OUTFILE. ARGS->DEPTH says how
+ far to indent. ARGS is really a struct print_symbol_args *, but is
+ declared as char * to get it past catch_errors. Returns 0 for error,
+ 1 for success. */
+
+static int
+print_symbol (args)
+ char *args;
+{
+ struct symbol *symbol = ((struct print_symbol_args *)args)->symbol;
+ int depth = ((struct print_symbol_args *)args)->depth;
+ FILE *outfile = ((struct print_symbol_args *)args)->outfile;
+
+ print_spaces (depth, outfile);
+ if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
+ {
+ fprintf (outfile, "label %s at 0x%lx\n", SYMBOL_SOURCE_NAME (symbol),
+ (unsigned long) SYMBOL_VALUE_ADDRESS (symbol));
+ return 1;
+ }
+ if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE)
+ {
+ if (TYPE_TAG_NAME (SYMBOL_TYPE (symbol)))
+ {
+ LA_PRINT_TYPE (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));
+ LA_PRINT_TYPE (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+ }
+ fprintf (outfile, ";\n");
+ }
+ else
+ {
+ if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
+ fprintf (outfile, "typedef ");
+ if (SYMBOL_TYPE (symbol))
+ {
+ /* Print details of types, except for enums where it's clutter. */
+ LA_PRINT_TYPE (SYMBOL_TYPE (symbol), SYMBOL_SOURCE_NAME (symbol),
+ outfile,
+ TYPE_CODE (SYMBOL_TYPE (symbol)) != TYPE_CODE_ENUM,
+ depth);
+ fprintf (outfile, "; ");
+ }
+ else
+ fprintf (outfile, "%s ", SYMBOL_SOURCE_NAME (symbol));
+
+ switch (SYMBOL_CLASS (symbol))
+ {
+ case LOC_CONST:
+ fprintf (outfile, "const %ld (0x%lx),",
+ SYMBOL_VALUE (symbol),
+ (unsigned long) 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, " %02x",
+ (unsigned)SYMBOL_VALUE_BYTES (symbol) [i]);
+ fprintf (outfile, ",");
+ }
+ break;
+
+ case LOC_STATIC:
+ fprintf (outfile, "static at 0x%lx,",
+ (unsigned long) 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%lx from fp,",
+ SYMBOL_VALUE (symbol));
+ break;
+
+ 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_REGPARM_ADDR:
+ fprintf (outfile, "address parameter register %ld,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_LOCAL:
+ fprintf (outfile, "local at 0x%lx,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_BASEREG:
+ fprintf (outfile, "local at 0x%lx from register %d",
+ SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol));
+ break;
+
+ case LOC_BASEREG_ARG:
+ fprintf (outfile, "arg at 0x%lx from register %d,",
+ SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol));
+ break;
+
+ case LOC_TYPEDEF:
+ break;
+
+ case LOC_LABEL:
+ fprintf (outfile, "label at 0x%lx",
+ (unsigned long) SYMBOL_VALUE_ADDRESS (symbol));
+ break;
+
+ case LOC_BLOCK:
+ fprintf (outfile, "block (object 0x%lx) starting at 0x%lx,",
+ (unsigned long) SYMBOL_BLOCK_VALUE (symbol),
+ (unsigned long) BLOCK_START (SYMBOL_BLOCK_VALUE (symbol)));
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ fprintf (outfile, "optimized out");
+ break;
+
+ default:
+ fprintf (outfile, "botched symbol class %x", SYMBOL_CLASS (symbol));
+ break;
+ }
+ }
+ fprintf (outfile, "\n");
+ return 1;
+}
+
+void
+maintenance_print_psymbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ FILE *outfile;
+ struct cleanup *cleanups;
+ char *symname = NULL;
+ char *filename = DEV_TTY;
+ struct objfile *objfile;
+ struct partial_symtab *ps;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("print-psymbols takes an output file name and optional symbol file name");
+ }
+ else if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup (freeargv, (char *) argv);
+
+ if (argv[0] != NULL)
+ {
+ filename = argv[0];
+ /* If a second arg is supplied, it is a source file name to match on */
+ if (argv[1] != NULL)
+ {
+ symname = argv[1];
+ }
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ outfile = fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup (fclose, outfile);
+
+ immediate_quit++;
+ ALL_PSYMTABS (objfile, ps)
+ if (symname == NULL || (STREQ (symname, ps -> filename)))
+ dump_psymtab (objfile, ps, outfile);
+ immediate_quit--;
+ do_cleanups (cleanups);
+}
+
+static void
+print_partial_symbol (p, count, what, outfile)
+ struct partial_symbol *p;
+ int count;
+ char *what;
+ FILE *outfile;
+{
+
+ fprintf_filtered (outfile, " %s partial symbols:\n", what);
+ while (count-- > 0)
+ {
+ fprintf_filtered (outfile, " `%s'", SYMBOL_NAME(p));
+ if (SYMBOL_DEMANGLED_NAME (p) != NULL)
+ {
+ fprintf_filtered (outfile, " `%s'", SYMBOL_DEMANGLED_NAME (p));
+ }
+ fputs_filtered (", ", outfile);
+ switch (SYMBOL_NAMESPACE (p))
+ {
+ case UNDEF_NAMESPACE:
+ fputs_filtered ("undefined namespace, ", outfile);
+ break;
+ case VAR_NAMESPACE:
+ /* This is the usual thing -- don't print it */
+ break;
+ case STRUCT_NAMESPACE:
+ fputs_filtered ("struct namespace, ", outfile);
+ break;
+ case LABEL_NAMESPACE:
+ fputs_filtered ("label namespace, ", outfile);
+ break;
+ default:
+ fputs_filtered ("<invalid namespace>, ", outfile);
+ break;
+ }
+ switch (SYMBOL_CLASS (p))
+ {
+ case LOC_UNDEF:
+ fputs_filtered ("undefined", outfile);
+ break;
+ case LOC_CONST:
+ fputs_filtered ("constant int", outfile);
+ break;
+ case LOC_STATIC:
+ fputs_filtered ("static", outfile);
+ break;
+ case LOC_REGISTER:
+ fputs_filtered ("register", outfile);
+ break;
+ case LOC_ARG:
+ fputs_filtered ("pass by value", outfile);
+ break;
+ case LOC_REF_ARG:
+ fputs_filtered ("pass by reference", outfile);
+ break;
+ case LOC_REGPARM:
+ fputs_filtered ("register parameter", outfile);
+ break;
+ case LOC_REGPARM_ADDR:
+ fputs_filtered ("register address parameter", outfile);
+ break;
+ case LOC_LOCAL:
+ fputs_filtered ("stack parameter", outfile);
+ break;
+ case LOC_TYPEDEF:
+ fputs_filtered ("type", outfile);
+ break;
+ case LOC_LABEL:
+ fputs_filtered ("label", outfile);
+ break;
+ case LOC_BLOCK:
+ fputs_filtered ("function", outfile);
+ break;
+ case LOC_CONST_BYTES:
+ fputs_filtered ("constant bytes", outfile);
+ break;
+ case LOC_LOCAL_ARG:
+ fputs_filtered ("shuffled arg", outfile);
+ break;
+ case LOC_OPTIMIZED_OUT:
+ fputs_filtered ("optimized out", outfile);
+ break;
+ default:
+ fputs_filtered ("<invalid location>", outfile);
+ break;
+ }
+ fputs_filtered (", ", outfile);
+ fprintf_filtered (outfile, "0x%lx\n", SYMBOL_VALUE (p));
+ p++;
+ }
+}
+
+void
+maintenance_print_msymbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ FILE *outfile;
+ struct cleanup *cleanups;
+ char *filename = DEV_TTY;
+ char *symname = NULL;
+ struct objfile *objfile;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("print-msymbols takes an output file name and optional symbol file name");
+ }
+ else if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup (freeargv, argv);
+
+ if (argv[0] != NULL)
+ {
+ filename = argv[0];
+ /* If a second arg is supplied, it is a source file name to match on */
+ if (argv[1] != NULL)
+ {
+ symname = argv[1];
+ }
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ outfile = fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup (fclose, outfile);
+
+ immediate_quit++;
+ ALL_OBJFILES (objfile)
+ if (symname == NULL || (STREQ (symname, objfile -> name)))
+ dump_msymbols (objfile, outfile);
+ immediate_quit--;
+ fprintf_filtered (outfile, "\n\n");
+ do_cleanups (cleanups);
+}
+
+void
+maintenance_print_objfiles (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ struct objfile *objfile;
+
+ dont_repeat ();
+
+ immediate_quit++;
+ ALL_OBJFILES (objfile)
+ dump_objfile (objfile);
+ immediate_quit--;
+}
+
+
+/* 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)) != NULL)
+ {
+ i++;
+ }
+ return i;
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+
+/* Increase the space allocated for LISTP, which is probably
+ global_psymbol_list or static_psymbol_list. This space will eventually
+ be freed in free_objfile(). */
+
+void
+extend_psymbol_list (listp, objfile)
+ register struct psymbol_allocation_list *listp;
+ struct objfile *objfile;
+{
+ int new_size;
+ if (listp->size == 0)
+ {
+ new_size = 255;
+ listp->list = (struct partial_symbol *)
+ xmmalloc (objfile -> md, new_size * sizeof (struct partial_symbol));
+ }
+ else
+ {
+ new_size = listp->size * 2;
+ listp->list = (struct partial_symbol *)
+ xmrealloc (objfile -> md, (char *) listp->list,
+ new_size * sizeof (struct partial_symbol));
+ }
+ /* Next assumes we only went one over. Should be good if
+ program works correctly */
+ listp->next = listp->list + listp->size;
+ listp->size = new_size;
+}
+
+
+/* Do early runtime initializations. */
+void
+_initialize_symmisc ()
+{
+ std_in = stdin;
+ std_out = stdout;
+ std_err = stderr;
+}
diff --git a/gnu/usr.bin/gdb/gdb/symtab.c b/gnu/usr.bin/gdb/gdb/symtab.c
new file mode 100644
index 000000000000..0d0255c73175
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/symtab.c
@@ -0,0 +1,3035 @@
+/* Symbol table lookup for the GNU debugger, GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "target.h"
+#include "value.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcmd.h"
+#include "call-cmds.h"
+#include "regex.h"
+#include "expression.h"
+#include "language.h"
+#include "demangle.h"
+
+#include <obstack.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+/* Prototypes for local functions */
+
+extern int
+find_methods PARAMS ((struct type *, char *, struct symbol **));
+
+static void
+completion_list_add_name PARAMS ((char *, char *, int, char *, char *));
+
+static void
+build_canonical_line_spec PARAMS ((struct symtab_and_line *, char *, char ***));
+
+static struct symtabs_and_lines
+decode_line_2 PARAMS ((struct symbol *[], int, int, char ***));
+
+static void
+rbreak_command PARAMS ((char *, int));
+
+static void
+types_info PARAMS ((char *, int));
+
+static void
+functions_info PARAMS ((char *, int));
+
+static void
+variables_info PARAMS ((char *, int));
+
+static void
+sources_info PARAMS ((char *, int));
+
+static void
+list_symbols PARAMS ((char *, int, int));
+
+static void
+output_source_filename PARAMS ((char *, int *));
+
+static char *
+operator_chars PARAMS ((char *, char **));
+
+static int find_line_common PARAMS ((struct linetable *, int, int *));
+
+static struct partial_symbol *
+lookup_partial_symbol PARAMS ((struct partial_symtab *, const char *,
+ int, enum namespace));
+
+static struct symtab *
+lookup_symtab_1 PARAMS ((char *));
+
+/* */
+
+/* The single non-language-specific builtin type */
+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. */
+
+const struct block *block_found;
+
+char no_symtab_msg[] = "No symbol table is loaded. Use the \"file\" command.";
+
+/* While the C++ support is still in flux, issue a possibly helpful hint on
+ using the new command completion feature on single quoted demangled C++
+ symbols. Remove when loose ends are cleaned up. FIXME -fnf */
+
+void
+cplusplus_hint (name)
+ char *name;
+{
+ printf ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name);
+ printf ("(Note leading single quote.)\n");
+}
+
+/* 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;
+ register struct objfile *objfile;
+
+ got_symtab:
+
+ /* First, search for an exact match */
+
+ ALL_SYMTABS (objfile, s)
+ if (STREQ (name, s->filename))
+ return s;
+
+ slash = strchr (name, '/');
+
+ /* Now, search for a matching tail (only if name doesn't have any dirs) */
+
+ if (!slash)
+ ALL_SYMTABS (objfile, s)
+ {
+ char *p = s -> filename;
+ char *tail = strrchr (p, '/');
+
+ if (tail)
+ p = tail + 1;
+
+ if (STREQ (p, name))
+ return s;
+ }
+
+ /* Same search rules as above apply here, but now we look thru the
+ psymtabs. */
+
+ ps = lookup_partial_symtab (name);
+ if (!ps)
+ return (NULL);
+
+ if (ps -> readin)
+ error ("Internal: readin %s pst for `%s' found when no symtab found.",
+ ps -> filename, name);
+
+ s = PSYMTAB_TO_SYMTAB (ps);
+
+ if (s)
+ return s;
+
+ /* At this point, we have located the psymtab for this file, but
+ the conversion to a symtab has failed. This usually happens
+ when we are looking up an include file. In this case,
+ PSYMTAB_TO_SYMTAB doesn't return a symtab, even though one has
+ been created. So, we need to run through the symtabs again in
+ order to find the file.
+ XXX - This is a crock, and should be fixed inside of the the
+ symbol parsing routines. */
+ goto got_symtab;
+}
+
+/* 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. */
+ /* Why is this? Is it just a user convenience? (If so, it's pretty
+ questionable in the presence of C++, FORTRAN, etc.). It's not in
+ the GDB manual. */
+
+ 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.
+ *If* there is no '/' in the name, a match after a '/'
+ in the psymtab filename will also work. */
+
+struct partial_symtab *
+lookup_partial_symtab (name)
+char *name;
+{
+ register struct partial_symtab *pst;
+ register struct objfile *objfile;
+
+ ALL_PSYMTABS (objfile, pst)
+ {
+ if (STREQ (name, pst -> filename))
+ {
+ return (pst);
+ }
+ }
+
+ /* Now, search for a matching tail (only if name doesn't have any dirs) */
+
+ if (!strchr (name, '/'))
+ ALL_PSYMTABS (objfile, pst)
+ {
+ char *p = pst -> filename;
+ char *tail = strrchr (p, '/');
+
+ if (tail)
+ p = tail + 1;
+
+ if (STREQ (p, name))
+ return (pst);
+ }
+
+ return (NULL);
+}
+
+/* Demangle a GDB method stub type.
+ Note that this function is g++ specific. */
+
+char *
+gdb_mangle_name (type, i, j)
+ struct type *type;
+ int i, j;
+{
+ int mangled_name_len;
+ char *mangled_name;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ struct fn_field *method = &f[j];
+ char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
+ char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
+ char *newname = type_name_no_tag (type);
+ int is_constructor;
+ int is_destructor = DESTRUCTOR_PREFIX_P (physname);
+ /* Need a new type prefix. */
+ char *const_prefix = method->is_const ? "C" : "";
+ char *volatile_prefix = method->is_volatile ? "V" : "";
+ char buf[20];
+ int len = (newname == NULL ? 0 : strlen (newname));
+ char *opname;
+
+ is_constructor = newname && STREQ(field_name, newname);
+ if (!is_constructor)
+ is_constructor = (physname[0]=='_' && physname[1]=='_' &&
+ (isdigit(physname[2]) || physname[2]=='Q' || physname[2]=='t'));
+ if (!is_constructor)
+ is_constructor = (strncmp(physname, "__ct", 4) == 0);
+ if (!is_destructor)
+ is_destructor = (strncmp(physname, "__dt", 4) == 0);
+
+#ifndef GCC_MANGLE_BUG
+ if (is_destructor)
+ {
+ mangled_name = (char*) xmalloc(strlen(physname)+1);
+ strcpy(mangled_name, physname);
+ return mangled_name;
+ }
+
+ if (len == 0)
+ {
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ if (strcmp(buf, "__") == 0)
+ buf[0] = '\0';
+ }
+ else
+ {
+ sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+ }
+ mangled_name_len = ((is_constructor ? 0 : strlen (field_name))
+ + strlen (buf) + len
+ + strlen (physname)
+ + 1);
+
+ /* Only needed for GNU-mangled names. ANSI-mangled names
+ work with the normal mechanisms. */
+ if (OPNAME_PREFIX_P (field_name))
+ {
+ char *opname = cplus_mangle_opname (field_name + 3, 0);
+ if (opname == NULL)
+ error ("No mangling for \"%s\"", field_name);
+ mangled_name_len += strlen (opname);
+ mangled_name = (char *)xmalloc (mangled_name_len);
+
+ strncpy (mangled_name, field_name, 3);
+ mangled_name[3] = '\0';
+ strcat (mangled_name, opname);
+ }
+ else
+ {
+ mangled_name = (char *)xmalloc (mangled_name_len);
+ if (is_constructor)
+ mangled_name[0] = '\0';
+ else
+ strcpy (mangled_name, field_name);
+ }
+ strcat (mangled_name, buf);
+ /* If the class doesn't have a name, i.e. newname NULL, then we just
+ mangle it using 0 for the length of the class. Thus it gets mangled
+ as something starting with `::' rather than `classname::'. */
+ if (newname != NULL)
+ strcat (mangled_name, newname);
+
+#else
+
+ if (is_constructor)
+ {
+ buf[0] = '\0';
+ }
+ else
+ {
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ }
+
+ mangled_name_len = ((is_constructor ? 0 : strlen (field_name))
+ + strlen (buf) + strlen (physname) + 1);
+
+ /* Only needed for GNU-mangled names. ANSI-mangled names
+ work with the normal mechanisms. */
+ if (OPNAME_PREFIX_P (field_name))
+ {
+ opname = cplus_mangle_opname (field_name + 3, 0);
+ if (opname == NULL)
+ {
+ error ("No mangling for \"%s\"", field_name);
+ }
+ mangled_name_len += strlen (opname);
+ mangled_name = (char *) xmalloc (mangled_name_len);
+
+ strncpy (mangled_name, field_name, 3);
+ strcpy (mangled_name + 3, opname);
+ }
+ else
+ {
+ mangled_name = (char *) xmalloc (mangled_name_len);
+ if (is_constructor)
+ {
+ mangled_name[0] = '\0';
+ }
+ else
+ {
+ strcpy (mangled_name, field_name);
+ }
+ }
+ strcat (mangled_name, buf);
+
+#endif
+ strcat (mangled_name, physname);
+ return (mangled_name);
+}
+
+
+/* Find which partial symtab on contains PC. Return 0 if none. */
+
+struct partial_symtab *
+find_pc_psymtab (pc)
+ register CORE_ADDR pc;
+{
+ register struct partial_symtab *pst;
+ register struct objfile *objfile;
+
+ ALL_PSYMTABS (objfile, pst)
+ {
+ if (pc >= pst->textlow && pc < pst->texthigh)
+ return (pst);
+ }
+ return (NULL);
+}
+
+/* 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 = NULL, *p;
+ CORE_ADDR best_pc;
+
+ if (!psymtab)
+ psymtab = find_pc_psymtab (pc);
+ if (!psymtab)
+ return 0;
+
+ best_pc = psymtab->textlow - 1;
+
+ for (p = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
+ (p - (psymtab->objfile->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;
+}
+
+
+/* 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)
+ const char *name;
+ register const struct block *block;
+ const enum namespace namespace;
+ int *is_a_field_of_this;
+ struct symtab **symtab;
+{
+ register struct symbol *sym;
+ register struct symtab *s = NULL;
+ register struct partial_symtab *ps;
+ struct blockvector *bv;
+ register struct objfile *objfile;
+ register struct block *b;
+ register struct minimal_symbol *msymbol;
+
+ /* 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. */
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ if (BLOCK_START (b) <= BLOCK_START (block)
+ && BLOCK_END (b) > BLOCK_START (block))
+ goto found;
+ }
+found:
+ *symtab = s;
+ }
+
+ return (sym);
+ }
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ /* FIXME: this code is never executed--block is always NULL at this
+ point. What is it trying to do, anyway? We already should have
+ checked the STATIC_BLOCK above (it is the superblock of top-level
+ blocks). Why is VAR_NAMESPACE special-cased? */
+ /* Don't need to mess with the psymtabs; if we have a block,
+ that file is read in. If we don't, then we deal later with
+ all the psymtab stuff that needs checking. */
+ if (namespace == VAR_NAMESPACE && block != NULL)
+ {
+ struct block *b;
+ /* Find the right symtab. */
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ if (BLOCK_START (b) <= BLOCK_START (block)
+ && BLOCK_END (b) > BLOCK_START (block))
+ {
+ sym = lookup_block_symbol (b, name, VAR_NAMESPACE);
+ if (sym)
+ {
+ block_found = b;
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+ }
+ }
+
+
+ /* 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 */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ 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 in one of the minimal symbol tables. Eventually, all
+ global symbols might be resolved in this way. */
+
+ if (namespace == VAR_NAMESPACE)
+ {
+ msymbol = lookup_minimal_symbol (name, (struct objfile *) NULL);
+ if (msymbol != NULL)
+ {
+ s = find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol));
+ /* If S is NULL, there are no debug symbols for this file.
+ Skip this stuff and check for matching static symbols below. */
+ if (s != NULL)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
+ namespace);
+ /* We kept static functions in minimal symbol table as well as
+ in static scope. We want to find them in the symbol table. */
+ if (!sym) {
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
+ namespace);
+ }
+
+ /* sym == 0 if symbol was found in the minimal symbol table
+ but not in the symtab.
+ Return 0 to use the msymbol 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;
+ }
+ }
+ }
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin && lookup_partial_symbol (ps, name, 1, namespace))
+ {
+ s = PSYMTAB_TO_SYMTAB(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (!sym)
+ error ("Internal: global symbol `%s' found in %s psymtab but not in symtab", name, ps->filename);
+ 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 */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin && lookup_partial_symbol (ps, name, 0, namespace))
+ {
+ s = PSYMTAB_TO_SYMTAB(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (!sym)
+ error ("Internal: static symbol `%s' found in %s psymtab but not in symtab", name, ps->filename);
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+
+ /* Now search all per-file blocks for static mangled symbols.
+ Do the symtabs first, then check the psymtabs. */
+
+ if (namespace == VAR_NAMESPACE)
+ {
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, VAR_NAMESPACE);
+ if (sym)
+ {
+ block_found = block;
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin && lookup_partial_symbol (ps, name, 0, VAR_NAMESPACE))
+ {
+ s = PSYMTAB_TO_SYMTAB(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, VAR_NAMESPACE);
+ if (!sym)
+ error ("Internal: mangled static symbol `%s' found in %s psymtab but not in symtab", name, ps->filename);
+ 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;
+ const char *name;
+ int global;
+ enum namespace namespace;
+{
+ struct partial_symbol *start, *psym;
+ struct partial_symbol *top, *bottom, *center;
+ int length = (global ? pst->n_global_syms : pst->n_static_syms);
+ int do_linear_search = 1;
+
+ if (length == 0)
+ {
+ return (NULL);
+ }
+
+ start = (global ?
+ pst->objfile->global_psymbols.list + pst->globals_offset :
+ pst->objfile->static_psymbols.list + pst->statics_offset );
+
+ if (global) /* This means we can use a binary search. */
+ {
+ do_linear_search = 0;
+
+ /* 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 (!do_linear_search && SYMBOL_LANGUAGE (center) == language_cplus)
+ {
+ do_linear_search = 1;
+ }
+ if (STRCMP (SYMBOL_NAME (center), name) >= 0)
+ {
+ top = center;
+ }
+ else
+ {
+ bottom = center + 1;
+ }
+ }
+ assert (top == bottom);
+ while (STREQ (SYMBOL_NAME (top), name))
+ {
+ if (SYMBOL_NAMESPACE (top) == namespace)
+ {
+ return top;
+ }
+ top ++;
+ }
+ }
+
+ /* Can't use a binary search or else we found during the binary search that
+ we should also do a linear search. */
+
+ if (do_linear_search)
+ {
+ for (psym = start; psym < start + length; psym++)
+ {
+ if (namespace == SYMBOL_NAMESPACE (psym))
+ {
+ if (SYMBOL_MATCHES_NAME (psym, name))
+ {
+ return (psym);
+ }
+ }
+ }
+ }
+
+ return (NULL);
+}
+
+/* Find the psymtab containing main(). */
+/* FIXME: What about languages without main() or specially linked
+ executables that have no main() ? */
+
+struct partial_symtab *
+find_main_psymtab ()
+{
+ register struct partial_symtab *pst;
+ register struct objfile *objfile;
+
+ ALL_PSYMTABS (objfile, pst)
+ {
+ if (lookup_partial_symbol (pst, "main", 1, VAR_NAMESPACE))
+ {
+ return (pst);
+ }
+ }
+ return (NULL);
+}
+
+/* Search BLOCK for symbol NAME in NAMESPACE.
+
+ Note that if NAME is the demangled form of a C++ symbol, we will fail
+ to find a match during the binary search of the non-encoded names, but
+ for now we don't worry about the slight inefficiency of looking for
+ a match we'll never find, since it will go pretty quick. Once the
+ binary search terminates, we drop through and do a straight linear
+ search on the symbols. Each symbol which is marked as being a C++
+ symbol (language_cplus set) has both the encoded and non-encoded names
+ tested for a match. */
+
+struct symbol *
+lookup_block_symbol (block, name, namespace)
+ register const struct block *block;
+ const char *name;
+ const enum namespace namespace;
+{
+ register int bot, top, inc;
+ register struct symbol *sym;
+ register struct symbol *sym_found = NULL;
+ register int do_linear_search = 1;
+
+ /* If the blocks's symbols were sorted, start with a binary search. */
+
+ if (BLOCK_SHOULD_SORT (block))
+ {
+ /* Reset the linear search flag so if the binary search fails, we
+ won't do the linear search once unless we find some reason to
+ do so, such as finding a C++ symbol during the binary search.
+ Note that for C++ modules, ALL the symbols in a block should
+ end up marked as C++ symbols. */
+
+ do_linear_search = 0;
+ top = BLOCK_NSYMS (block);
+ bot = 0;
+
+ /* 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 (!do_linear_search && SYMBOL_LANGUAGE (sym) == language_cplus)
+ {
+ do_linear_search = 1;
+ }
+ 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; I believe it is now impossible for us
+ to encounter two symbols with the same name and namespace
+ here, because blocks containing argument symbols are no
+ longer sorted. */
+
+ 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)
+ {
+ break;
+ }
+ bot++;
+ }
+ }
+
+ /* Here if block isn't sorted, or we fail to find a match during the
+ binary search above. If during the binary search above, we find a
+ symbol which is a C++ symbol, then we have re-enabled the linear
+ search flag which was reset when starting the binary search.
+
+ 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. */
+
+ if (do_linear_search)
+ {
+ top = BLOCK_NSYMS (block);
+ bot = 0;
+ while (bot < top)
+ {
+ sym = BLOCK_SYM (block, bot);
+ if (SYMBOL_NAMESPACE (sym) == namespace &&
+ SYMBOL_MATCHES_NAME (sym, name))
+ {
+ sym_found = sym;
+ if (SYMBOL_CLASS (sym) != LOC_ARG &&
+ SYMBOL_CLASS (sym) != LOC_LOCAL_ARG &&
+ SYMBOL_CLASS (sym) != LOC_REF_ARG &&
+ SYMBOL_CLASS (sym) != LOC_REGPARM &&
+ SYMBOL_CLASS (sym) != LOC_REGPARM_ADDR &&
+ SYMBOL_CLASS (sym) != LOC_BASEREG_ARG)
+ {
+ break;
+ }
+ }
+ bot++;
+ }
+ }
+ return (sym_found); /* Will be NULL if not found. */
+}
+
+
+/* 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);
+}
+
+/* Find the symtab associated with PC. Look through the psymtabs and read in
+ another symtab if necessary. */
+
+struct symtab *
+find_pc_symtab (pc)
+ register CORE_ADDR pc;
+{
+ register struct block *b;
+ struct blockvector *bv;
+ register struct symtab *s = NULL;
+ register struct symtab *best_s = NULL;
+ register struct partial_symtab *ps;
+ register struct objfile *objfile;
+ int distance = 0;
+
+ /* Search all symtabs for the one whose file contains our address, and which
+ is the smallest of all the ones containing the address. This is designed
+ to deal with a case like symtab a is at 0x1000-0x2000 and 0x3000-0x4000
+ and symtab b is at 0x2000-0x3000. So the GLOBAL_BLOCK for a is from
+ 0x1000-0x4000, but for address 0x2345 we want to return symtab b.
+ This is said to happen for the mips; it might be swifter to create
+ several symtabs with the same name like xcoff does (I'm not sure). */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ if (BLOCK_START (b) <= pc
+ && BLOCK_END (b) > pc
+ && (distance == 0
+ || BLOCK_END (b) - BLOCK_START (b) < distance))
+ {
+ distance = BLOCK_END (b) - BLOCK_START (b);
+ best_s = s;
+ }
+ }
+
+ if (best_s != NULL)
+ return(best_s);
+
+ s = NULL;
+ ps = find_pc_psymtab (pc);
+ if (ps)
+ {
+ if (ps->readin)
+ /* Might want to error() here (in case symtab is corrupt and
+ will cause a core dump), but maybe we can successfully
+ continue, so let's not. */
+ warning ("\
+(Internal error: pc 0x%lx in read in psymtab, but not in symtab.)\n",
+ (unsigned long) pc);
+ 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. */
+
+/* The big complication here is that a line may start in one file, and end just
+ before the start of another file. This usually occurs when you #include
+ code in the middle of a subroutine. To properly find the end of a line's PC
+ range, we must search all symtabs associated with this compilation unit, and
+ find the one whose first PC is closer than that of the next line in this
+ symtab. */
+
+/* If it's worth the effort, we could be using a binary search. */
+
+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. */
+
+ struct linetable_entry *best = NULL;
+ 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. */
+ struct linetable_entry *alt = NULL;
+ struct symtab *alt_symtab = 0;
+
+ /* Info on best line seen in this file. */
+
+ struct linetable_entry *prev;
+
+ /* 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)
+ {
+ 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);
+ if (!l)
+ continue;
+ len = l->nitems;
+ if (len <= 0)
+ {
+ /* I think len can be zero if the symtab lacks line numbers
+ (e.g. gcc -g1). (Either that or the LINETABLE is NULL;
+ I'm not sure which, and maybe it depends on the symbol
+ reader). */
+ continue;
+ }
+
+ prev = NULL;
+ item = l->item; /* Get first line info */
+
+ /* 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 (item->pc > pc && (!alt || item->pc < alt->pc))
+ {
+ alt = item;
+ alt_symtab = s;
+ }
+
+ for (i = 0; i < len; i++, item++)
+ {
+ /* Return the last line that did not start after PC. */
+ if (item->pc > pc)
+ break;
+
+ prev = item;
+ }
+
+ /* At this point, prev points at the line whose start addr is <= pc, and
+ item points at the next line. If we ran off the end of the linetable
+ (pc >= start of the last line), then prev == item. If pc < start of
+ the first line, prev will not be set. */
+
+ /* 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 && (!best || prev->pc > best->pc))
+ {
+ best = prev;
+ best_symtab = s;
+ /* If another line is in the linetable, and its PC is closer
+ than the best_end we currently have, take it as best_end. */
+ if (i < len && (best_end == 0 || best_end > item->pc))
+ best_end = item->pc;
+ }
+ }
+
+ if (!best_symtab)
+ {
+ if (!alt_symtab)
+ { /* If we didn't find any line # info, just
+ return zeros. */
+ val.symtab = 0;
+ val.line = 0;
+ val.pc = pc;
+ val.end = 0;
+ }
+ else
+ {
+ val.symtab = alt_symtab;
+ val.line = alt->line - 1;
+ val.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
+ val.end = alt->pc;
+ }
+ }
+ else
+ {
+ val.symtab = best_symtab;
+ val.line = best->line;
+ val.pc = best->pc;
+ if (best_end && (!alt || best_end < alt->pc))
+ val.end = best_end;
+ else if (alt)
+ val.end = alt->pc;
+ else
+ val.end = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
+ }
+ return val;
+}
+
+static int find_line_symtab PARAMS ((struct symtab *, int, struct linetable **,
+ int *, int *));
+
+/* Find line number LINE in any symtab whose name is the same as
+ SYMTAB.
+
+ If found, return 1, set *LINETABLE to the linetable in which it was
+ found, set *INDEX to the index in the linetable of the best entry
+ found, and set *EXACT_MATCH nonzero if the value returned is an
+ exact match.
+
+ If not found, return 0. */
+
+static int
+find_line_symtab (symtab, line, linetable, index, exact_match)
+ struct symtab *symtab;
+ int line;
+ struct linetable **linetable;
+ int *index;
+ int *exact_match;
+{
+ int exact;
+
+ /* BEST_INDEX and BEST_LINETABLE identify the smallest linenumber > LINE
+ so far seen. */
+
+ int best_index;
+ struct linetable *best_linetable;
+
+ /* First try looking it up in the given symtab. */
+ best_linetable = LINETABLE (symtab);
+ best_index = find_line_common (best_linetable, line, &exact);
+ if (best_index < 0 || !exact)
+ {
+ /* Didn't find an exact match. So we better keep looking for
+ another symtab with the same name. In the case of xcoff,
+ multiple csects for one source file (produced by IBM's FORTRAN
+ compiler) produce multiple symtabs (this is unavoidable
+ assuming csects can be at arbitrary places in memory and that
+ the GLOBAL_BLOCK of a symtab has a begin and end address). */
+
+ /* BEST is the smallest linenumber > LINE so far seen,
+ or 0 if none has been seen so far.
+ BEST_INDEX and BEST_LINETABLE identify the item for it. */
+ int best;
+
+ struct objfile *objfile;
+ struct symtab *s;
+
+ if (best_index >= 0)
+ best = best_linetable->item[best_index].line;
+ else
+ best = 0;
+
+ ALL_SYMTABS (objfile, s)
+ {
+ struct linetable *l;
+ int ind;
+
+ if (!STREQ (symtab->filename, s->filename))
+ continue;
+ l = LINETABLE (s);
+ ind = find_line_common (l, line, &exact);
+ if (ind >= 0)
+ {
+ if (exact)
+ {
+ best_index = ind;
+ best_linetable = l;
+ goto done;
+ }
+ if (best == 0 || l->item[ind].line < best)
+ {
+ best = l->item[ind].line;
+ best_index = ind;
+ best_linetable = l;
+ }
+ }
+ }
+ }
+ done:
+ if (best_index < 0)
+ return 0;
+
+ if (index)
+ *index = best_index;
+ if (linetable)
+ *linetable = best_linetable;
+ if (exact_match)
+ *exact_match = exact;
+ return 1;
+}
+
+/* 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;
+{
+ struct linetable *l;
+ int ind;
+
+ if (symtab == 0)
+ return 0;
+ if (find_line_symtab (symtab, line, &l, &ind, NULL))
+ return l->item[ind].pc;
+ else
+ return 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;
+{
+ struct linetable *l;
+ int ind;
+ int exact_match; /* did we get an exact linenumber match */
+
+ if (symtab == 0)
+ return 0;
+
+ if (find_line_symtab (symtab, thisline, &l, &ind, &exact_match))
+ {
+ *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 -1 if none is found. The value is >= 0 if 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 = -1;
+ int best = 0;
+
+ if (lineno <= 0)
+ return -1;
+ if (l == 0)
+ return -1;
+
+ len = l->nitems;
+ for (i = 0; i < len; i++)
+ {
+ register struct linetable_entry *item = &(l->item[i]);
+
+ if (item->line == lineno)
+ {
+ /* Return the first (lowest address) entry which matches. */
+ *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;
+}
+
+/* If P is of the form "operator[ \t]+..." where `...' is
+ some legitimate operator text, return a pointer to the
+ beginning of the substring of the operator text.
+ Otherwise, return "". */
+static char *
+operator_chars (p, end)
+ char *p;
+ char **end;
+{
+ *end = "";
+ if (strncmp (p, "operator", 8))
+ return *end;
+ p += 8;
+
+ /* Don't get faked out by `operator' being part of a longer
+ identifier. */
+ if (isalpha(*p) || *p == '_' || *p == '$' || *p == '\0')
+ return *end;
+
+ /* Allow some whitespace between `operator' and the operator symbol. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* Recognize 'operator TYPENAME'. */
+
+ if (isalpha(*p) || *p == '_' || *p == '$')
+ {
+ register char *q = p+1;
+ while (isalnum(*q) || *q == '_' || *q == '$')
+ q++;
+ *end = q;
+ return p;
+ }
+
+ switch (*p)
+ {
+ case '!':
+ case '=':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ if (p[1] == '=')
+ *end = p+2;
+ else
+ *end = p+1;
+ return p;
+ case '<':
+ case '>':
+ case '+':
+ case '-':
+ case '&':
+ case '|':
+ if (p[1] == '=' || p[1] == p[0])
+ *end = p+2;
+ else
+ *end = p+1;
+ return p;
+ case '~':
+ case ',':
+ *end = p+1;
+ return p;
+ case '(':
+ if (p[1] != ')')
+ error ("`operator ()' must be specified without whitespace in `()'");
+ *end = p+2;
+ return p;
+ case '?':
+ if (p[1] != ':')
+ error ("`operator ?:' must be specified without whitespace in `?:'");
+ *end = p+2;
+ return p;
+ case '[':
+ if (p[1] != ']')
+ error ("`operator []' must be specified without whitespace in `[]'");
+ *end = p+2;
+ return p;
+ default:
+ error ("`operator %s' not supported", p);
+ break;
+ }
+ *end = "";
+ return *end;
+}
+
+/* Recursive helper function for decode_line_1.
+ * Look for methods named NAME in type T.
+ * Return number of matches.
+ * Put matches in 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*));
+ * Note that this function is g++ specific.
+ */
+
+int
+find_methods (t, name, sym_arr)
+ struct type *t;
+ char *name;
+ 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 is ugly, but
+ unless we figure out how to get the physname without the name of
+ the class, then the loop can't do any good. */
+ if (class_name
+ && (sym_class = lookup_symbol (class_name,
+ (struct block *)NULL,
+ STRUCT_NAMESPACE,
+ (int *)NULL,
+ (struct symtab **)NULL)))
+ {
+ int method_counter;
+ /* FIXME: Shouldn't this just be check_stub_type (t)? */
+ 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 (STREQ (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_FN_FIELD_STUB (f, field_counter))
+ check_stub_method (t, method_counter, field_counter);
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+ /* Destructor is handled by caller, dont add it to the list */
+ if (DESTRUCTOR_PREFIX_P (phys_name))
+ continue;
+
+ /* FIXME: Why are we looking this up in the
+ SYMBOL_BLOCK_VALUE (sym_class)? It is intended as a hook
+ for nested types? If so, it should probably hook to the
+ type, not the symbol. mipsread.c is the only symbol
+ reader which sets the SYMBOL_BLOCK_VALUE for types, and
+ this is not documented in symtab.h. -26Aug93. */
+
+ sym_arr[i1] = lookup_symbol (phys_name,
+ SYMBOL_BLOCK_VALUE (sym_class),
+ VAR_NAMESPACE,
+ (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym_arr[i1]) i1++;
+ else
+ {
+ fputs_filtered("(Cannot find method ", stdout);
+ fprintf_symbol_filtered (stdout, phys_name,
+ language_cplus, DMGL_PARAMS);
+ fputs_filtered(" - possibly inlined.)\n", stdout);
+ }
+ }
+ }
+ }
+
+ /* Only search baseclasses if there is no match yet, since names in
+ derived classes override those in baseclasses.
+
+ FIXME: The above is not true; it is only true of member functions
+ if they have the same number of arguments (??? - section 13.1 of the
+ ARM says the function members are not in the same scope but doesn't
+ really spell out the rules in a way I understand. In any case, if
+ the number of arguments differ this is a case in which we can overload
+ rather than hiding without any problem, and gcc 2.4.5 does overload
+ rather than hiding in this case). */
+
+ if (i1)
+ return i1;
+ for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
+ i1 += find_methods(TYPE_BASECLASS(t, ibase), name,
+ sym_arr + i1);
+ return i1;
+}
+
+/* Helper function for decode_line_1.
+ Build a canonical line spec in CANONICAL if it is non-NULL and if
+ the SAL has a symtab.
+ If SYMNAME is non-NULL the canonical line spec is `filename:symname'.
+ If SYMNAME is NULL the line number from SAL is used and the canonical
+ line spec is `filename:linenum'. */
+
+static void
+build_canonical_line_spec (sal, symname, canonical)
+ struct symtab_and_line *sal;
+ char *symname;
+ char ***canonical;
+{
+ char **canonical_arr;
+ char *canonical_name;
+ char *filename;
+ struct symtab *s = sal->symtab;
+
+ if (s == (struct symtab *)NULL
+ || s->filename == (char *)NULL
+ || canonical == (char ***)NULL)
+ return;
+
+ canonical_arr = (char **) xmalloc (sizeof (char *));
+ *canonical = canonical_arr;
+
+ filename = s->filename;
+ if (symname != NULL)
+ {
+ canonical_name = xmalloc (strlen (filename) + strlen (symname) + 2);
+ sprintf (canonical_name, "%s:%s", filename, symname);
+ }
+ else
+ {
+ canonical_name = xmalloc (strlen (filename) + 30);
+ sprintf (canonical_name, "%s:%d", filename, sal->line);
+ }
+ canonical_arr[0] = canonical_name;
+}
+
+/* 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 minimal symbol table.
+
+ 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.
+ If CANONICAL is non-NULL, store an array of strings containing the canonical
+ line specs there if necessary. Currently overloaded member functions and
+ line numbers or static functions without a filename yield a canonical
+ line spec. The array and the line spec strings are allocated on the heap,
+ it is the callers responsibility to free them.
+
+ 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, canonical)
+ char **argptr;
+ int funfirstline;
+ struct symtab *default_symtab;
+ int default_line;
+ char ***canonical;
+{
+ struct symtabs_and_lines values;
+#ifdef HPPA_COMPILER_BUG
+ /* FIXME: The native HP 9000/700 compiler has a bug which appears
+ when optimizing this file with target i960-vxworks. I haven't
+ been able to construct a simple test case. The problem is that
+ in the second call to SKIP_PROLOGUE below, the compiler somehow
+ does not realize that the statement val = find_pc_line (...) will
+ change the values of the fields of val. It extracts the elements
+ into registers at the top of the block, and does not update the
+ registers after the call to find_pc_line. You can check this by
+ inserting a printf at the end of find_pc_line to show what values
+ it is returning for val.pc and val.end and another printf after
+ the call to see what values the function actually got (remember,
+ this is compiling with cc -O, with this patch removed). You can
+ also examine the assembly listing: search for the second call to
+ skip_prologue; the LDO statement before the next call to
+ find_pc_line loads the address of the structure which
+ find_pc_line will return; if there is a LDW just before the LDO,
+ which fetches an element of the structure, then the compiler
+ still has the bug.
+
+ Setting val to volatile avoids the problem. We must undef
+ volatile, because the HPPA native compiler does not define
+ __STDC__, although it does understand volatile, and so volatile
+ will have been defined away in defs.h. */
+#undef volatile
+ volatile struct symtab_and_line val;
+#define volatile /*nothing*/
+#else
+ struct symtab_and_line val;
+#endif
+ register char *p, *p1;
+ char *q, *q1;
+ register struct symtab *s;
+
+ register struct symbol *sym;
+ /* The symtab that SYM was found in. */
+ struct symtab *sym_symtab;
+
+ register CORE_ADDR pc;
+ register struct minimal_symbol *msymbol;
+ char *copy;
+ struct symbol *sym_class;
+ int i1;
+ int is_quoted;
+ struct symbol **sym_arr;
+ struct type *t;
+ char *saved_arg = *argptr;
+ extern char *gdb_completer_quote_characters;
+
+ /* Defaults have defaults. */
+
+ if (default_symtab == 0)
+ {
+ default_symtab = current_source_symtab;
+ default_line = current_source_line;
+ }
+
+ /* See if arg is *PC */
+
+ if (**argptr == '*')
+ {
+ 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;
+ build_canonical_line_spec (values.sals, NULL, canonical);
+ return values;
+ }
+
+ /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+
+ s = NULL;
+ is_quoted = (strchr (gdb_completer_quote_characters, **argptr) != NULL);
+
+ for (p = *argptr; *p; p++)
+ {
+ if (p[0] == ':' || p[0] == ' ' || p[0] == '\t')
+ break;
+ }
+ while (p[0] == ' ' || p[0] == '\t') p++;
+
+ if ((p[0] == ':') && !is_quoted)
+ {
+
+ /* C++ */
+ if (p[1] ==':')
+ {
+ /* Extract the class name. */
+ p1 = p;
+ while (p != *argptr && p[-1] == ' ') --p;
+ copy = (char *) alloca (p - *argptr + 1);
+ memcpy (copy, *argptr, 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++;
+ q = operator_chars (*argptr, &q1);
+
+ if (q1 - q)
+ {
+ char *opname;
+ char *tmp = alloca (q1 - q + 1);
+ memcpy (tmp, q, q1 - q);
+ tmp[q1 - q] = '\0';
+ opname = cplus_mangle_opname (tmp, DMGL_ANSI);
+ if (opname == NULL)
+ {
+ warning ("no mangling for \"%s\"", tmp);
+ cplusplus_hint (saved_arg);
+ return_to_top_level (RETURN_ERROR);
+ }
+ copy = (char*) alloca (3 + strlen(opname));
+ sprintf (copy, "__%s", opname);
+ p = q1;
+ }
+ else
+ {
+ copy = (char *) alloca (p - *argptr + 1 + (q1 - q));
+ memcpy (copy, *argptr, 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*));
+
+ /* Cfront objects don't have fieldlists. */
+ if (destructor_name_p (copy, t) && TYPE_FN_FIELDLISTS (t) != NULL)
+ {
+ /* destructors are a special case. */
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (t, 0);
+ int len = TYPE_FN_FIELDLIST_LENGTH (t, 0) - 1;
+ /* gcc 1.x puts destructor in last field,
+ gcc 2.x puts destructor in first field. */
+ char *phys_name = TYPE_FN_FIELD_PHYSNAME (f, len);
+ if (!DESTRUCTOR_PREFIX_P (phys_name))
+ {
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, 0);
+ if (!DESTRUCTOR_PREFIX_P (phys_name))
+ 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, 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, canonical);
+ }
+ else
+ {
+ char *tmp;
+
+ if (OPNAME_PREFIX_P (copy))
+ {
+ tmp = (char *)alloca (strlen (copy+3) + 9);
+ strcpy (tmp, "operator ");
+ strcat (tmp, copy+3);
+ }
+ else
+ tmp = copy;
+ if (tmp[0] == '~')
+ warning ("the class `%s' does not have destructor defined",
+ SYMBOL_SOURCE_NAME(sym_class));
+ else
+ warning ("the class %s does not have any method named %s",
+ SYMBOL_SOURCE_NAME(sym_class), tmp);
+ cplusplus_hint (saved_arg);
+ return_to_top_level (RETURN_ERROR);
+ }
+ }
+ else
+ {
+ /* The quotes are important if copy is empty. */
+ warning ("can't find class, struct, or union named \"%s\"",
+ copy);
+ cplusplus_hint (saved_arg);
+ return_to_top_level (RETURN_ERROR);
+ }
+ }
+ /* end of C++ */
+
+
+ /* Extract the file name. */
+ p1 = p;
+ while (p != *argptr && p[-1] == ' ') --p;
+ copy = (char *) alloca (p - *argptr + 1);
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = 0;
+
+ /* Find that file's data. */
+ s = lookup_symtab (copy);
+ if (s == 0)
+ {
+ if (!have_full_symbols () && !have_partial_symbols ())
+ 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;
+
+ /* We might need a canonical line spec if no file was specified. */
+ int need_canonical = (s == 0) ? 1 : 0;
+
+ /* 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)
+ {
+ 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;
+ if (need_canonical)
+ build_canonical_line_spec (values.sals, NULL, canonical);
+ 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 = skip_quoted (*argptr);
+ if (is_quoted && p[-1] != '\'')
+ error ("Unmatched single quote.");
+ copy = (char *) alloca (p - *argptr + 1);
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = '\0';
+ if ((copy[0] == copy [p - *argptr - 1])
+ && strchr (gdb_completer_quote_characters, copy[0]) != NULL)
+ {
+ copy [p - *argptr - 1] = '\0';
+ copy++;
+ }
+ 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), STATIC_BLOCK)
+ : 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
+ /* Check if SKIP_PROLOGUE left us in mid-line, and the next
+ line is still part of the same function. */
+ if (val.pc != pc
+ && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= val.end
+ && val.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
+ {
+ /* First pc of next line */
+ pc = val.end;
+ /* Recalculate the line number (might not be N+1). */
+ val = find_pc_line (pc, 0);
+ }
+ val.pc = 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);
+
+ /* We might need a canonical line spec if it is a static function. */
+ if (s == 0)
+ {
+ struct blockvector *bv = BLOCKVECTOR (sym_symtab);
+ struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ if (lookup_block_symbol (b, copy, VAR_NAMESPACE) != NULL)
+ build_canonical_line_spec (values.sals, copy, canonical);
+ }
+ 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;
+ memset (&values.sals[0], 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. */
+ /* FIXME: Shouldn't we just set .line and .symtab to zero and
+ return? For example, "info line foo" could print the address. */
+ error ("Line number not known for symbol \"%s\"", copy);
+ }
+
+ msymbol = lookup_minimal_symbol (copy, (struct objfile *) NULL);
+ if (msymbol != NULL)
+ {
+ val.symtab = 0;
+ val.line = 0;
+ val.pc = SYMBOL_VALUE_ADDRESS (msymbol) + 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;
+ }
+
+ if (!have_full_symbols () &&
+ !have_partial_symbols () && !have_minimal_symbols ())
+ error (no_symtab_msg);
+
+ 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,
+ (char ***)NULL);
+ if (*string)
+ error ("Junk at end of line specification: %s", string);
+ return sals;
+}
+
+/* Given a list of NELTS symbols in SYM_ARR, return a list of lines to
+ operate on (ask user if necessary).
+ If CANONICAL is non-NULL return a corresponding array of mangled names
+ as canonical line specs there. */
+
+static struct symtabs_and_lines
+decode_line_2 (sym_arr, nelts, funfirstline, canonical)
+ struct symbol *sym_arr[];
+ int nelts;
+ int funfirstline;
+ char ***canonical;
+{
+ struct symtabs_and_lines values, return_values;
+ register CORE_ADDR pc;
+ char *args, *arg1;
+ int i;
+ char *prompt;
+ char *symname;
+ struct cleanup *old_chain;
+ char **canonical_arr = (char **)NULL;
+
+ 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));
+ old_chain = make_cleanup (free, return_values.sals);
+
+ if (canonical)
+ {
+ canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
+ make_cleanup (free, canonical_arr);
+ memset (canonical_arr, 0, nelts * sizeof (char *));
+ *canonical = canonical_arr;
+ }
+
+ 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] %s at %s:%d\n", (i+2), SYMBOL_SOURCE_NAME (sym_arr[i]),
+ 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 ((char *) NULL, 0);
+
+ if (args == 0 || *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)
+ {
+ if (canonical_arr)
+ {
+ for (i = 0; i < nelts; i++)
+ {
+ if (canonical_arr[i] == NULL)
+ {
+ symname = SYMBOL_NAME (sym_arr[i]);
+ canonical_arr[i] = savestring (symname, strlen (symname));
+ }
+ }
+ }
+ memcpy (return_values.sals, values.sals,
+ (nelts * sizeof(struct symtab_and_line)));
+ return_values.nelts = nelts;
+ discard_cleanups (old_chain);
+ return return_values;
+ }
+
+ if (num > nelts + 2)
+ {
+ printf ("No choice number %d.\n", num);
+ }
+ else
+ {
+ num -= 2;
+ if (values.sals[num].pc)
+ {
+ if (canonical_arr)
+ {
+ symname = SYMBOL_NAME (sym_arr[num]);
+ make_cleanup (free, symname);
+ canonical_arr[i] = savestring (symname, strlen (symname));
+ }
+ 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;
+ discard_cleanups (old_chain);
+ return return_values;
+}
+
+
+/* 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;
+{
+ /* 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 (STREQ (*p, name))
+ /* 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 ((char *) tab, tab_alloc_size * sizeof (*tab));
+ }
+ tab[tab_cur_size++] = name;
+
+ if (*first)
+ {
+ *first = 0;
+ }
+ else
+ {
+ printf_filtered (", ");
+ }
+
+ wrap_here ("");
+ fputs_filtered (name, stdout);
+}
+
+static void
+sources_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct objfile *objfile;
+ int first;
+
+ if (!have_full_symbols () && !have_partial_symbols ())
+ {
+ error (no_symtab_msg);
+ }
+
+ printf_filtered ("Source files for which symbols have been read in:\n\n");
+
+ first = 1;
+ ALL_SYMTABS (objfile, s)
+ {
+ 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;
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin)
+ {
+ output_source_filename (ps -> filename, &first);
+ }
+ }
+ printf_filtered ("\n");
+}
+
+/* List all symbols (if REGEXP is NULL) or all symbols matching REGEXP.
+ If CLASS is zero, list all symbols except functions, type names, and
+ constants (enums).
+ If CLASS is 1, list only functions.
+ If CLASS is 2, list only type names.
+ If CLASS is 3, list only method 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;
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ char *val;
+ static char *classnames[]
+ = {"variable", "function", "type", "method"};
+ int found_in_file = 0;
+ int found_misc = 0;
+ static enum minimal_symbol_type types[]
+ = {mst_data, mst_text, mst_abs, mst_unknown};
+ static enum minimal_symbol_type types2[]
+ = {mst_bss, mst_text, mst_abs, mst_unknown};
+ enum minimal_symbol_type ourtype = types[class];
+ enum minimal_symbol_type ourtype2 = types2[class];
+
+ if (regexp != NULL)
+ {
+ /* Make sure spacing is right for C++ operators.
+ This is just a courtesy to make the matching less sensitive
+ to how many spaces the user leaves between 'operator'
+ and <TYPENAME> or <OPERATOR>. */
+ char *opend;
+ char *opname = operator_chars (regexp, &opend);
+ if (*opname)
+ {
+ int fix = -1; /* -1 means ok; otherwise number of spaces needed. */
+ if (isalpha(*opname) || *opname == '_' || *opname == '$')
+ {
+ /* There should 1 space between 'operator' and 'TYPENAME'. */
+ if (opname[-1] != ' ' || opname[-2] == ' ')
+ fix = 1;
+ }
+ else
+ {
+ /* There should 0 spaces between 'operator' and 'OPERATOR'. */
+ if (opname[-1] == ' ')
+ fix = 0;
+ }
+ /* If wrong number of spaces, fix it. */
+ if (fix >= 0)
+ {
+ char *tmp = (char*) alloca(opend-opname+10);
+ sprintf(tmp, "operator%.*s%s", fix, " ", opname);
+ regexp = tmp;
+ }
+ }
+
+ if (0 != (val = re_comp (regexp)))
+ error ("Invalid regexp (%s): %s", val, regexp);
+ }
+
+ /* Search through the partial symtabs *first* for all symbols
+ matching the regexp. That way we don't have to reproduce all of
+ the machinery below. */
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ struct partial_symbol *bound, *gbound, *sbound;
+ int keep_going = 1;
+
+ if (ps->readin) continue;
+
+ gbound = objfile->global_psymbols.list + ps->globals_offset + ps->n_global_syms;
+ sbound = objfile->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 = objfile->global_psymbols.list + ps->globals_offset;
+ while (keep_going)
+ {
+ if (psym >= bound)
+ {
+ if (bound == gbound && ps->n_static_syms != 0)
+ {
+ psym = objfile->static_psymbols.list + ps->statics_offset;
+ bound = sbound;
+ }
+ else
+ keep_going = 0;
+ continue;
+ }
+ else
+ {
+ QUIT;
+
+ /* If it would match (logic taken from loop below)
+ load the file and go on to the next one */
+ if ((regexp == NULL || SYMBOL_MATCHES_REGEXP (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)))
+ {
+ PSYMTAB_TO_SYMTAB(ps);
+ keep_going = 0;
+ }
+ }
+ psym++;
+ }
+ }
+
+ /* Here, we search through the minimal symbol tables for functions 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 find_pc_symtab fails, set found_misc so that we will
+ rescan to print any matching symbols without debug info. */
+
+ if (class == 1)
+ {
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ if (MSYMBOL_TYPE (msymbol) == ourtype ||
+ MSYMBOL_TYPE (msymbol) == ourtype2)
+ {
+ if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
+ {
+ if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
+ {
+ found_misc = 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* 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);
+
+ ALL_SYMTABS (objfile, s)
+ {
+ 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 = GLOBAL_BLOCK; i <= STATIC_BLOCK; 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 == NULL || SYMBOL_MATCHES_REGEXP (sym))
+ && ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (sym) != LOC_BLOCK
+ && SYMBOL_CLASS (sym) != LOC_CONST)
+ || (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)
+ {
+ /* There may be more than one function with the
+ same name but in different files. In order to
+ set breakpoints on all of them, we must give
+ both the file name and the function name to
+ break_command. */
+ char *string =
+ (char *) alloca (strlen (s->filename)
+ + strlen (SYMBOL_NAME(sym))
+ + 2);
+ strcpy (string, s->filename);
+ strcat (string, ":");
+ strcat (string, SYMBOL_NAME(sym));
+ break_command (string, 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 == STATIC_BLOCK)
+ printf_filtered ("static ");
+
+ /* Typedef that is not a C++ class */
+ if (class == 2
+ && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
+ c_typedef_print (SYMBOL_TYPE(sym), sym, stdout);
+ /* variable, func, or typedef-that-is-c++-class */
+ else if (class < 2 ||
+ (class == 2 &&
+ SYMBOL_NAMESPACE(sym) == STRUCT_NAMESPACE))
+ {
+ type_print (SYMBOL_TYPE (sym),
+ (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ ? "" : SYMBOL_SOURCE_NAME (sym)),
+ stdout, 0);
+
+ printf_filtered (";\n");
+ }
+ else
+ {
+# if 0 /* FIXME, why is this zapped out? */
+ char buf[1024];
+ c_type_print_base (TYPE_FN_FIELD_TYPE(t, i),
+ stdout, 0, 0);
+ c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i),
+ stdout, 0);
+ sprintf (buf, " %s::", type_name_no_tag (t));
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (t, i),
+ buf, name, stdout);
+# endif
+ }
+ }
+ }
+ }
+ prev_bv = bv;
+ }
+
+ /* If there are no eyes, avoid all contact. I mean, if there are
+ no debug symbols, then print directly from the msymbol_vector. */
+
+ if (found_misc || class != 1)
+ {
+ found_in_file = 0;
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ if (MSYMBOL_TYPE (msymbol) == ourtype ||
+ MSYMBOL_TYPE (msymbol) == ourtype2)
+ {
+ if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
+ {
+ /* Functions: Look up by address. */
+ if (class != 1 ||
+ (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))))
+ {
+ /* Variables/Absolutes: Look up by name */
+ if (lookup_symbol (SYMBOL_NAME (msymbol),
+ (struct block *) NULL, VAR_NAMESPACE,
+ 0, (struct symtab **) NULL) == NULL)
+ {
+ if (!found_in_file)
+ {
+ printf_filtered ("\nNon-debugging symbols:\n");
+ found_in_file = 1;
+ }
+ printf_filtered (" %08lx %s\n",
+ (unsigned long) SYMBOL_VALUE_ADDRESS (msymbol),
+ SYMBOL_SOURCE_NAME (msymbol));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void
+variables_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ list_symbols (regexp, 0, 0);
+}
+
+static void
+functions_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ list_symbols (regexp, 1, 0);
+}
+
+static void
+types_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ list_symbols (regexp, 2, 0);
+}
+
+#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, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ list_symbols (regexp, 1, 1);
+}
+
+
+/* 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);
+}
+
+
+/* Helper routine for make_symbol_completion_list. */
+
+static int return_val_size;
+static int return_val_index;
+static char **return_val;
+
+#define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
+ do { \
+ if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) \
+ /* Put only the mangled name on the list. */ \
+ /* Advantage: "b foo<TAB>" completes to "b foo(int, int)" */ \
+ /* Disadvantage: "b foo__i<TAB>" doesn't complete. */ \
+ completion_list_add_name \
+ (SYMBOL_DEMANGLED_NAME (symbol), (sym_text), (len), (text), (word)); \
+ else \
+ completion_list_add_name \
+ (SYMBOL_NAME (symbol), (sym_text), (len), (text), (word)); \
+ } while (0)
+
+/* Test to see if the symbol specified by SYMNAME (which is already
+ demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
+ characters. If so, add it to the current completion list. */
+
+static void
+completion_list_add_name (symname, sym_text, sym_text_len, text, word)
+ char *symname;
+ char *sym_text;
+ int sym_text_len;
+ char *text;
+ char *word;
+{
+ int newsize;
+ int i;
+
+ /* clip symbols that cannot match */
+
+ if (strncmp (symname, sym_text, sym_text_len) != 0)
+ {
+ return;
+ }
+
+ /* Clip any symbol names that we've already considered. (This is a
+ time optimization) */
+
+ for (i = 0; i < return_val_index; ++i)
+ {
+ if (STREQ (symname, return_val[i]))
+ {
+ return;
+ }
+ }
+
+ /* We have a match for a completion, so add SYMNAME to the current list
+ of matches. Note that the name is moved to freshly malloc'd space. */
+
+ {
+ char *new;
+ if (word == sym_text)
+ {
+ new = xmalloc (strlen (symname) + 5);
+ strcpy (new, symname);
+ }
+ else if (word > sym_text)
+ {
+ /* Return some portion of symname. */
+ new = xmalloc (strlen (symname) + 5);
+ strcpy (new, symname + (word - sym_text));
+ }
+ else
+ {
+ /* Return some of SYM_TEXT plus symname. */
+ new = xmalloc (strlen (symname) + (sym_text - word) + 5);
+ strncpy (new, word, sym_text - word);
+ new[sym_text - word] = '\0';
+ strcat (new, symname);
+ }
+
+ if (return_val_index + 3 > return_val_size)
+ {
+ newsize = (return_val_size *= 2) * sizeof (char *);
+ return_val = (char **) xrealloc ((char *) return_val, newsize);
+ }
+ return_val[return_val_index++] = new;
+ return_val[return_val_index] = 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, word)
+ char *text;
+ char *word;
+{
+ register struct symbol *sym;
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct minimal_symbol *msymbol;
+ register struct objfile *objfile;
+ register struct block *b, *surrounding_static_block = 0;
+ register int i, j;
+ struct partial_symbol *psym;
+ /* The symbol we are completing on. Points in same buffer as text. */
+ char *sym_text;
+ /* Length of sym_text. */
+ int sym_text_len;
+
+ /* Now look for the symbol we are supposed to complete on.
+ FIXME: This should be language-specific. */
+ {
+ char *p;
+ char quote_found;
+ char *quote_pos = NULL;
+
+ /* First see if this is a quoted string. */
+ quote_found = '\0';
+ for (p = text; *p != '\0'; ++p)
+ {
+ if (quote_found != '\0')
+ {
+ if (*p == quote_found)
+ /* Found close quote. */
+ quote_found = '\0';
+ else if (*p == '\\' && p[1] == quote_found)
+ /* A backslash followed by the quote character
+ doesn't end the string. */
+ ++p;
+ }
+ else if (*p == '\'' || *p == '"')
+ {
+ quote_found = *p;
+ quote_pos = p;
+ }
+ }
+ if (quote_found == '\'')
+ /* A string within single quotes can be a symbol, so complete on it. */
+ sym_text = quote_pos + 1;
+ else if (quote_found == '"')
+ /* A double-quoted string is never a symbol, nor does it make sense
+ to complete it any other way. */
+ return NULL;
+ else
+ {
+ /* It is not a quoted string. Break it based on the characters
+ which are in symbols. */
+ while (p > text)
+ {
+ if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
+ --p;
+ else
+ break;
+ }
+ sym_text = p;
+ }
+ }
+
+ sym_text_len = strlen (sym_text);
+
+ return_val_size = 100;
+ return_val_index = 0;
+ return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
+ return_val[0] = NULL;
+
+ /* Look through the partial symtabs for all symbols which begin
+ by matching SYM_TEXT. Add each one that you find to the list. */
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ /* If the psymtab's been read in we'll get it when we search
+ through the blockvector. */
+ if (ps->readin) continue;
+
+ for (psym = objfile->global_psymbols.list + ps->globals_offset;
+ psym < (objfile->global_psymbols.list + ps->globals_offset
+ + ps->n_global_syms);
+ psym++)
+ {
+ /* If interrupted, then quit. */
+ QUIT;
+ COMPLETION_LIST_ADD_SYMBOL (psym, sym_text, sym_text_len, text, word);
+ }
+
+ for (psym = objfile->static_psymbols.list + ps->statics_offset;
+ psym < (objfile->static_psymbols.list + ps->statics_offset
+ + ps->n_static_syms);
+ psym++)
+ {
+ QUIT;
+ COMPLETION_LIST_ADD_SYMBOL (psym, sym_text, sym_text_len, text, word);
+ }
+ }
+
+ /* At this point scan through the misc symbol vectors 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). */
+
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ QUIT;
+ COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
+ }
+
+ /* Search upwards from currently selected frame (so that we can
+ complete on local vars. */
+
+ for (b = get_selected_block (); b != NULL; 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++)
+ {
+ sym = BLOCK_SYM (b, i);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ 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))
+ {
+ completion_list_add_name (TYPE_FIELD_NAME (t, j),
+ sym_text, sym_text_len, text, word);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Go through the symtabs and check the externs and statics for
+ symbols which match. */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ }
+ }
+
+ ALL_SYMTABS (objfile, s)
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ /* Don't do this block twice. */
+ if (b == surrounding_static_block) continue;
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ }
+ }
+
+ return (return_val);
+}
+
+
+#if 0
+/* Add the type of the symbol sym to the type of the current
+ function whose block we are in (assumed). The type of
+ this current function is contained in *TYPE.
+
+ This basically works as follows: When we find a function
+ symbol (N_FUNC with a 'f' or 'F' in the symbol name), we record
+ a pointer to its type in the global in_function_type. Every
+ time we come across a parameter symbol ('p' in its name), then
+ this procedure adds the name and type of that parameter
+ to the function type pointed to by *TYPE. (Which should correspond
+ to in_function_type if it was called correctly).
+
+ Note that since we are modifying a type, the result of
+ lookup_function_type() should be memcpy()ed before calling
+ this. When not in strict typing mode, the expression
+ evaluator can choose to ignore this.
+
+ Assumption: All of a function's parameter symbols will
+ appear before another function symbol is found. The parameters
+ appear in the same order in the argument list as they do in the
+ symbol table. */
+
+void
+add_param_to_type (type,sym)
+ struct type **type;
+ struct symbol *sym;
+{
+ int num = ++(TYPE_NFIELDS(*type));
+
+ if(TYPE_NFIELDS(*type)-1)
+ TYPE_FIELDS(*type) = (struct field *)
+ (*current_objfile->xrealloc) ((char *)(TYPE_FIELDS(*type)),
+ num*sizeof(struct field));
+ else
+ TYPE_FIELDS(*type) = (struct field *)
+ (*current_objfile->xmalloc) (num*sizeof(struct field));
+
+ TYPE_FIELD_BITPOS(*type,num-1) = num-1;
+ TYPE_FIELD_BITSIZE(*type,num-1) = 0;
+ TYPE_FIELD_TYPE(*type,num-1) = SYMBOL_TYPE(sym);
+ TYPE_FIELD_NAME(*type,num-1) = SYMBOL_NAME(sym);
+}
+#endif
+
+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.");
+
+ /* FIXME: 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 type names, or those matching REGEXP.");
+
+#if 0
+ add_info ("methods", methods_info,
+ "All method names, or those matching REGEXP::REGEXP.\n\
+If the class qualifier is omitted, it is assumed to be the current scope.\n\
+If the first REGEXP is omitted, 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.");
+
+ /* Initialize the one built-in type that isn't language dependent... */
+ builtin_type_error = init_type (TYPE_CODE_ERROR, 0, 0,
+ "<unknown type>", (struct objfile *) NULL);
+}
diff --git a/gnu/usr.bin/gdb/gdb/symtab.h b/gnu/usr.bin/gdb/gdb/symtab.h
new file mode 100644
index 000000000000..9570b393adbf
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/symtab.h
@@ -0,0 +1,1124 @@
+/* Symbol table definitions for GDB.
+ Copyright (C) 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (SYMTAB_H)
+#define SYMTAB_H 1
+
+/* Some definitions and declarations to go with use of obstacks. */
+
+#include "obstack.h"
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
+/* Define a structure for the information that is common to all symbol types,
+ including minimal symbols, partial symbols, and full symbols. In a
+ multilanguage environment, some language specific information may need to
+ be recorded along with each symbol. */
+
+struct general_symbol_info
+{
+ /* Name of the symbol. This is a required field. Storage for the name is
+ allocated on the psymbol_obstack or symbol_obstack for the associated
+ objfile. */
+
+ char *name;
+
+ /* Value of the symbol. Which member of this union to use, and what
+ it means, depends on what kind of symbol this is and its
+ SYMBOL_CLASS. See comments there for more details. 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;
+
+ struct block *block;
+
+ char *bytes;
+
+ CORE_ADDR address;
+
+ /* for opaque typedef struct chain */
+
+ struct symbol *chain;
+ }
+ value;
+
+ /* Record the source code language that applies to this symbol.
+ This is used to select one of the fields from the language specific
+ union below. */
+
+ enum language language;
+
+ /* Since one and only one language can apply, wrap the language specific
+ information inside a union. */
+
+ union
+ {
+ struct cplus_specific /* For C++ */
+ {
+ char *demangled_name;
+ } cplus_specific;
+ struct chill_specific /* For Chill */
+ {
+ char *demangled_name;
+ } chill_specific;
+ } language_specific;
+
+ /* Which section is this symbol in? This is an index into
+ section_offsets for this objfile. Negative means that the symbol
+ does not get relocated relative to a section.
+ Disclaimer: currently this is just used for xcoff, so don't
+ expect all symbol-reading code to set it correctly (the ELF code
+ also tries to set it correctly). */
+
+ int section;
+};
+
+#define SYMBOL_NAME(symbol) (symbol)->ginfo.name
+#define SYMBOL_VALUE(symbol) (symbol)->ginfo.value.value
+#define SYMBOL_VALUE_ADDRESS(symbol) (symbol)->ginfo.value.address
+#define SYMBOL_VALUE_BYTES(symbol) (symbol)->ginfo.value.bytes
+#define SYMBOL_BLOCK_VALUE(symbol) (symbol)->ginfo.value.block
+#define SYMBOL_VALUE_CHAIN(symbol) (symbol)->ginfo.value.chain
+#define SYMBOL_LANGUAGE(symbol) (symbol)->ginfo.language
+#define SYMBOL_SECTION(symbol) (symbol)->ginfo.section
+
+#define SYMBOL_CPLUS_DEMANGLED_NAME(symbol) \
+ (symbol)->ginfo.language_specific.cplus_specific.demangled_name
+
+
+extern int demangle; /* We reference it, so go ahead and declare it. */
+
+/* Macro that initializes the language dependent portion of a symbol
+ depending upon the language for the symbol. */
+
+#define SYMBOL_INIT_LANGUAGE_SPECIFIC(symbol,language) \
+ do { \
+ SYMBOL_LANGUAGE (symbol) = language; \
+ if (SYMBOL_LANGUAGE (symbol) == language_cplus) \
+ { \
+ SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \
+ } \
+ else if (SYMBOL_LANGUAGE (symbol) == language_chill) \
+ { \
+ SYMBOL_CHILL_DEMANGLED_NAME (symbol) = NULL; \
+ } \
+ else \
+ { \
+ memset (&(symbol)->ginfo.language_specific, 0, \
+ sizeof ((symbol)->ginfo.language_specific)); \
+ } \
+ } while (0)
+
+/* Macro that attempts to initialize the demangled name for a symbol,
+ based on the language of that symbol. If the language is set to
+ language_auto, it will attempt to find any demangling algorithm
+ that works and then set the language appropriately. If no demangling
+ of any kind is found, the language is set back to language_unknown,
+ so we can avoid doing this work again the next time we encounter
+ the symbol. Any required space to store the name is obtained from the
+ specified obstack. */
+
+#define SYMBOL_INIT_DEMANGLED_NAME(symbol,obstack) \
+ do { \
+ char *demangled = NULL; \
+ if (SYMBOL_LANGUAGE (symbol) == language_cplus \
+ || SYMBOL_LANGUAGE (symbol) == language_auto) \
+ { \
+ demangled = \
+ cplus_demangle (SYMBOL_NAME (symbol), DMGL_PARAMS | DMGL_ANSI);\
+ if (demangled != NULL) \
+ { \
+ SYMBOL_LANGUAGE (symbol) = language_cplus; \
+ SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = \
+ obsavestring (demangled, strlen (demangled), (obstack)); \
+ free (demangled); \
+ } \
+ else \
+ { \
+ SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \
+ } \
+ } \
+ if (demangled == NULL \
+ && (SYMBOL_LANGUAGE (symbol) == language_chill \
+ || SYMBOL_LANGUAGE (symbol) == language_auto)) \
+ { \
+ demangled = \
+ chill_demangle (SYMBOL_NAME (symbol)); \
+ if (demangled != NULL) \
+ { \
+ SYMBOL_LANGUAGE (symbol) = language_chill; \
+ SYMBOL_CHILL_DEMANGLED_NAME (symbol) = \
+ obsavestring (demangled, strlen (demangled), (obstack)); \
+ free (demangled); \
+ } \
+ else \
+ { \
+ SYMBOL_CHILL_DEMANGLED_NAME (symbol) = NULL; \
+ } \
+ } \
+ if (SYMBOL_LANGUAGE (symbol) == language_auto) \
+ { \
+ SYMBOL_LANGUAGE (symbol) = language_unknown; \
+ } \
+ } while (0)
+
+/* Macro that returns the demangled name for a symbol based on the language
+ for that symbol. If no demangled name exists, returns NULL. */
+
+#define SYMBOL_DEMANGLED_NAME(symbol) \
+ (SYMBOL_LANGUAGE (symbol) == language_cplus \
+ ? SYMBOL_CPLUS_DEMANGLED_NAME (symbol) \
+ : (SYMBOL_LANGUAGE (symbol) == language_chill \
+ ? SYMBOL_CHILL_DEMANGLED_NAME (symbol) \
+ : NULL))
+
+#define SYMBOL_CHILL_DEMANGLED_NAME(symbol) \
+ (symbol)->ginfo.language_specific.chill_specific.demangled_name
+
+/* Macro that returns the "natural source name" of a symbol. In C++ this is
+ the "demangled" form of the name if demangle is on and the "mangled" form
+ of the name if demangle is off. In other languages this is just the
+ symbol name. The result should never be NULL. */
+
+#define SYMBOL_SOURCE_NAME(symbol) \
+ (demangle && SYMBOL_DEMANGLED_NAME (symbol) != NULL \
+ ? SYMBOL_DEMANGLED_NAME (symbol) \
+ : SYMBOL_NAME (symbol))
+
+/* Macro that returns the "natural assembly name" of a symbol. In C++ this is
+ the "mangled" form of the name if demangle is off, or if demangle is on and
+ asm_demangle is off. Otherwise if asm_demangle is on it is the "demangled"
+ form. In other languages this is just the symbol name. The result should
+ never be NULL. */
+
+#define SYMBOL_LINKAGE_NAME(symbol) \
+ (demangle && asm_demangle && SYMBOL_DEMANGLED_NAME (symbol) != NULL \
+ ? SYMBOL_DEMANGLED_NAME (symbol) \
+ : SYMBOL_NAME (symbol))
+
+/* From utils.c. */
+extern int demangle;
+extern int asm_demangle;
+
+/* Macro that tests a symbol for a match against a specified name string.
+ First test the unencoded name, then looks for and test a C++ encoded
+ name if it exists. Note that whitespace is ignored while attempting to
+ match a C++ encoded name, so that "foo::bar(int,long)" is the same as
+ "foo :: bar (int, long)".
+ Evaluates to zero if the match fails, or nonzero if it succeeds. */
+
+#define SYMBOL_MATCHES_NAME(symbol, name) \
+ (STREQ (SYMBOL_NAME (symbol), (name)) \
+ || (SYMBOL_DEMANGLED_NAME (symbol) != NULL \
+ && strcmp_iw (SYMBOL_DEMANGLED_NAME (symbol), (name)) == 0))
+
+/* Macro that tests a symbol for an re-match against the last compiled regular
+ expression. First test the unencoded name, then look for and test a C++
+ encoded name if it exists.
+ Evaluates to zero if the match fails, or nonzero if it succeeds. */
+
+#define SYMBOL_MATCHES_REGEXP(symbol) \
+ (re_exec (SYMBOL_NAME (symbol)) != 0 \
+ || (SYMBOL_DEMANGLED_NAME (symbol) != NULL \
+ && re_exec (SYMBOL_DEMANGLED_NAME (symbol)) != 0))
+
+/* Define a simple structure used to hold some very basic information about
+ all defined global symbols (text, data, bss, abs, etc). The only required
+ information is the general_symbol_info.
+
+ In many cases, even if a file was compiled with no special options for
+ debugging at all, as long as was not stripped it will contain sufficient
+ information to build a useful minimal symbol table using this structure.
+ Even when a file contains enough debugging information to build a full
+ symbol table, these minimal symbols are still useful for quickly mapping
+ between names and addresses, and vice versa. They are also sometimes
+ used to figure out what full symbol table entries need to be read in. */
+
+struct minimal_symbol
+{
+
+ /* The general symbol info required for all types of symbols.
+
+ The SYMBOL_VALUE_ADDRESS contains the address that this symbol
+ corresponds to. */
+
+ struct general_symbol_info ginfo;
+
+ /* The info field is available for caching machine-specific information that
+ 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. Storage for any data
+ pointed to by this field should be allocated on the symbol_obstack for
+ the associated objfile. The type would be "void *" except for reasons
+ of compatibility with older compilers. This field is optional. */
+
+ char *info;
+
+ /* Classification types for this symbol. These should be taken as "advisory
+ only", since if gdb can't easily figure out a classification it simply
+ selects mst_unknown. It may also have to guess when it can't figure out
+ which is a better match between two types (mst_data versus mst_bss) for
+ example. Since the minimal symbol info is sometimes derived from the
+ BFD library's view of a file, we need to live with what information bfd
+ supplies. */
+
+ enum minimal_symbol_type
+ {
+ mst_unknown = 0, /* Unknown type, the default */
+ mst_text, /* Generally executable instructions */
+ mst_data, /* Generally initialized data */
+ mst_bss, /* Generally uninitialized data */
+ mst_abs, /* Generally absolute (nonrelocatable) */
+ /* For the mst_file* types, the names are only guaranteed to be unique
+ within a given .o file. */
+ mst_file_text, /* Static version of mst_text */
+ mst_file_data, /* Static version of mst_data */
+ mst_file_bss /* Static version of mst_bss */
+ } type;
+
+};
+
+#define MSYMBOL_INFO(msymbol) (msymbol)->info
+#define MSYMBOL_TYPE(msymbol) (msymbol)->type
+
+
+/* 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 blockvector begins with some special blocks.
+ The GLOBAL_BLOCK contains all the symbols defined in this compilation
+ whose scope is the entire program linked together.
+ The STATIC_BLOCK contains all the symbols whose scope is the
+ entire compilation excluding other separate compilations.
+ Blocks starting with the FIRST_LOCAL_BLOCK are not special.
+
+ Each block records a range of core addresses for the code that
+ is in the scope of the block. The STATIC_BLOCK and GLOBAL_BLOCK
+ 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];
+};
+
+#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks
+#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
+
+/* Special block numbers */
+
+#define GLOBAL_BLOCK 0
+#define STATIC_BLOCK 1
+#define FIRST_LOCAL_BLOCK 2
+
+struct block
+{
+
+ /* Addresses in the executable code that are in this block. */
+
+ CORE_ADDR startaddr;
+ CORE_ADDR endaddr;
+
+ /* The symbol that names this block, if the block is the body of a
+ function; otherwise, zero. */
+
+ struct symbol *function;
+
+ /* The `struct block' for the containing block, or 0 if none.
+
+ The superblock of a top-level local block (i.e. a function in the
+ case of C) is the STATIC_BLOCK. The superblock of the
+ STATIC_BLOCK is the GLOBAL_BLOCK. */
+
+ struct block *superblock;
+
+ /* Version of GCC used to compile the function corresponding
+ to this block, or 0 if not compiled with GCC. When possible,
+ GCC should be compatible with the native compiler, or if that
+ is not feasible, the differences should be fixed during symbol
+ reading. As of 16 Apr 93, this flag is never used to distinguish
+ between gcc2 and the native compiler.
+
+ If there is no function corresponding to this block, this meaning
+ of this flag is undefined. */
+
+ unsigned char gcc_compile_flag;
+
+ /* Number of local symbols. */
+
+ int nsyms;
+
+ /* The symbols. If some of them are arguments, then they must be
+ in the order in which we would like to print them. */
+
+ struct symbol *sym[1];
+};
+
+#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.
+ Don't sort a block which corresponds to a function. If we did the
+ sorting would have to preserve the order of the symbols for the
+ arguments. */
+
+#define BLOCK_SHOULD_SORT(bl) ((bl)->nsyms >= 40 && BLOCK_FUNCTION (bl) == NULL)
+
+
+/* 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. */
+
+enum namespace
+{
+ /* UNDEF_NAMESPACE is used when a namespace has not been discovered or
+ none of the following apply. This usually indicates an error either
+ in the symbol information or in gdb's handling of symbols. */
+
+ UNDEF_NAMESPACE,
+
+ /* VAR_NAMESPACE is the usual namespace. In C, this contains variables,
+ function names, typedef names and enum type values. */
+
+ VAR_NAMESPACE,
+
+ /* 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. */
+
+ 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. */
+
+ LABEL_NAMESPACE
+};
+
+/* An address-class says where to find the value of a symbol. */
+
+enum address_class
+{
+ /* Not used; catches errors */
+
+ LOC_UNDEF,
+
+ /* Value is constant int SYMBOL_VALUE, host byteorder */
+
+ LOC_CONST,
+
+ /* Value is at fixed address SYMBOL_VALUE_ADDRESS */
+
+ LOC_STATIC,
+
+ /* Value is in register. SYMBOL_VALUE is the register number. */
+
+ LOC_REGISTER,
+
+ /* It's an argument; the value is at SYMBOL_VALUE offset in arglist. */
+
+ LOC_ARG,
+
+ /* Value address is at SYMBOL_VALUE offset in arglist. */
+
+ LOC_REF_ARG,
+
+ /* Value is in register number SYMBOL_VALUE. Just like LOC_REGISTER
+ except this is an argument. Probably the cleaner way to handle
+ this would be to separate address_class (which would include
+ separate ARG and LOCAL to deal with FRAME_ARGS_ADDRESS versus
+ FRAME_LOCALS_ADDRESS), and an is_argument flag.
+
+ For some symbol formats (stabs, for some compilers at least),
+ the compiler generates two symbols, an argument and a register.
+ In some cases we combine them to a single LOC_REGPARM in symbol
+ reading, but currently not for all cases (e.g. it's passed on the
+ stack and then loaded into a register). */
+
+ LOC_REGPARM,
+
+ /* Value is in specified register. Just like LOC_REGPARM except the
+ register holds the address of the argument instead of the argument
+ itself. This is currently used for the passing of structs and unions
+ on sparc and hppa. It is also used for call by reference where the
+ address is in a register, at least by mipsread.c. */
+
+ LOC_REGPARM_ADDR,
+
+ /* Value is a local variable at SYMBOL_VALUE offset in stack frame. */
+
+ LOC_LOCAL,
+
+ /* Value not used; definition in SYMBOL_TYPE. Symbols in the namespace
+ STRUCT_NAMESPACE all have this class. */
+
+ LOC_TYPEDEF,
+
+ /* Value is address SYMBOL_VALUE_ADDRESS in the code */
+
+ LOC_LABEL,
+
+ /* In a symbol table, value is SYMBOL_BLOCK_VALUE of a `struct block'.
+ In a partial symbol table, SYMBOL_VALUE_ADDRESS is the start address
+ of the block. Function names have this class. */
+
+ LOC_BLOCK,
+
+ /* Value is a constant byte-sequence pointed to by SYMBOL_VALUE_BYTES, in
+ target byte order. */
+
+ LOC_CONST_BYTES,
+
+ /* Value is arg at SYMBOL_VALUE 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. */
+
+ LOC_LOCAL_ARG,
+
+ /* Value is at SYMBOL_VALUE offset from the current value of
+ register number SYMBOL_BASEREG. This exists mainly for the same
+ things that LOC_LOCAL and LOC_ARG do; but we need to do this
+ instead because on 88k DWARF gives us the offset from the
+ frame/stack pointer, rather than the offset from the "canonical
+ frame address" used by COFF, stabs, etc., and we don't know how
+ to convert between these until we start examining prologues.
+
+ Note that LOC_BASEREG is much less general than a DWARF expression.
+ We don't need the generality (at least not yet), and storing a general
+ DWARF expression would presumably take up more space than the existing
+ scheme. */
+
+ LOC_BASEREG,
+
+ /* Same as LOC_BASEREG but it is an argument. */
+
+ LOC_BASEREG_ARG,
+
+ /* The variable does not actually exist in the program.
+ The value is ignored. */
+
+ LOC_OPTIMIZED_OUT
+};
+
+struct symbol
+{
+
+ /* The general symbol info required for all types of symbols. */
+
+ struct general_symbol_info ginfo;
+
+ /* Name space code. */
+
+ enum namespace namespace;
+
+ /* Address class */
+
+ enum address_class class;
+
+ /* Data type of value */
+
+ struct type *type;
+
+ /* Line number of definition. FIXME: Should we really make the assumption
+ that nobody will try to debug files longer than 64K lines? What about
+ machine generated programs? */
+
+ unsigned short line;
+
+ /* Some symbols require an additional value to be recorded on a per-
+ symbol basis. Stash those values here. */
+
+ union
+ {
+ /* Used by LOC_BASEREG and LOC_BASEREG_ARG. */
+ short basereg;
+ }
+ aux_value;
+
+};
+
+#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace
+#define SYMBOL_CLASS(symbol) (symbol)->class
+#define SYMBOL_TYPE(symbol) (symbol)->type
+#define SYMBOL_LINE(symbol) (symbol)->line
+#define SYMBOL_BASEREG(symbol) (symbol)->aux_value.basereg
+
+/* 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 a partial symtab list and which points to the corresponding
+ normal symtab once the partial_symtab has been referenced. */
+
+struct partial_symbol
+{
+
+ /* The general symbol info required for all types of symbols. */
+
+ struct general_symbol_info ginfo;
+
+ /* Name space code. */
+
+ enum namespace namespace;
+
+ /* Address class (for info_symbols) */
+
+ enum address_class class;
+
+};
+
+#define PSYMBOL_NAMESPACE(psymbol) (psymbol)->namespace
+#define PSYMBOL_CLASS(psymbol) (psymbol)->class
+
+
+/* Source-file information. This describes the relation between source files,
+ ine 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. */
+
+struct linetable_entry
+{
+ int line;
+ CORE_ADDR pc;
+};
+
+/* The order of entries in the linetable is significant. They should
+ be sorted by increasing values of the pc field. If there is more than
+ one entry for a given pc, then I'm not sure what should happen (and
+ I not sure whether we currently handle it the best way).
+
+ Example: a C for statement generally looks like this
+
+ 10 0x100 - for the init/test part of a for stmt.
+ 20 0x200
+ 30 0x300
+ 10 0x400 - for the increment part of a for stmt.
+
+ */
+
+struct linetable
+{
+ int nitems;
+
+ /* Actually NITEMS elements. If you don't like this use of the
+ `struct hack', you can shove it up your ANSI (seriously, if the
+ committee tells us how to do it, we can probably go along). */
+ struct linetable_entry item[1];
+};
+
+/* All the information on one source file. */
+
+struct source
+{
+ char *name; /* Name of file */
+ struct linetable contents;
+};
+
+/* How to relocate the symbols from each section in a symbol file.
+ Each struct contains an array of offsets.
+ The ordering and meaning of the offsets is file-type-dependent;
+ typically it is indexed by section numbers or symbol types or
+ something like that.
+
+ To give us flexibility in changing the internal representation
+ of these offsets, the ANOFFSET macro must be used to insert and
+ extract offset values in the struct. */
+
+struct section_offsets
+ {
+ CORE_ADDR offsets[1]; /* As many as needed. */
+ };
+
+#define ANOFFSET(secoff, whichone) (secoff->offsets[whichone])
+
+/* Each source file or header 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. May be shared
+ between different symtabs (and normally is for all the symtabs
+ in a given compilation unit). */
+
+ struct blockvector *blockvector;
+
+ /* Table mapping core addresses to line numbers for this file.
+ Can be NULL if none. Never shared between different symtabs. */
+
+ struct linetable *linetable;
+
+ /* Section in objfile->section_offsets for the blockvector and
+ the linetable. */
+
+ int block_line_section;
+
+ /* If several symtabs share a blockvector, exactly one of them
+ should be designed the primary, so that the blockvector
+ is relocated exactly once by objfile_relocate. */
+
+ int primary;
+
+ /* 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. FIXME: Is this redundant
+ with the primary field? */
+
+ 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;
+
+ /* line_charpos[N] is the position of the (N-1)th line of the
+ source file. "position" means something we can lseek() to; it
+ is not guaranteed to be useful any other way. */
+
+ 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.
+ NULL if not yet known. */
+
+ char *fullname;
+
+ /* Object file from which this symbol information was read. */
+
+ struct objfile *objfile;
+
+ /* Anything extra for this symtab. This is for target machines
+ with special debugging info of some sort (which cannot just
+ be represented in a normal symtab). */
+
+#if defined (EXTRA_SYMTAB_INFO)
+ EXTRA_SYMTAB_INFO
+#endif
+
+ };
+
+#define BLOCKVECTOR(symtab) (symtab)->blockvector
+#define LINETABLE(symtab) (symtab)->linetable
+
+
+/* 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 lists.
+
+ 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;
+
+ /* Information about the object file from which symbols should be read. */
+
+ struct objfile *objfile;
+
+ /* Set of relocation offsets to apply to each section. */
+
+ struct section_offsets *section_offsets;
+
+ /* Range of text addresses covered by this file; texthigh is the
+ beginning of the next section. */
+
+ CORE_ADDR textlow;
+ CORE_ADDR 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. "depends on" means that symbols must be read
+ for the dependencies before being read for this psymtab; this is
+ for type references in stabs, where if foo.c includes foo.h, declarations
+ in foo.h may use type numbers defined in foo.c. For other debugging
+ formats there may be no need to use dependencies. */
+
+ 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 global_psymbols[]. */
+
+ int globals_offset;
+ int 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). This is an offset and size within
+ static_psymbols[]. */
+
+ int statics_offset;
+ int 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) PARAMS ((struct partial_symtab *));
+
+ /* Information that lets read_symtab() locate the part of the symbol table
+ that this psymtab corresponds to. This information is private to the
+ format-dependent symbol reading routines. For further detail examine
+ the various symbol reading modules. Should really be (void *) but is
+ (char *) as with other such gdb variables. (FIXME) */
+
+ char *read_symtab_private;
+
+ /* 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 != NULL ? (pst) -> symtab : psymtab_to_symtab (pst))
+
+
+/* The virtual function table is now an array of structures which have the
+ form { int16 offset, delta; void *pfn; }.
+
+ In normal virtual function tables, OFFSET is unused.
+ DELTA is the amount which is added to the apparent object's base
+ address in order to point to the actual object to which the
+ virtual function should be applied.
+ PFN is a pointer to the virtual function.
+
+ Note that this macro is g++ specific (FIXME). */
+
+#define VTBL_FNADDR_OFFSET 2
+
+/* Macro that yields non-zero value iff NAME is the prefix for C++ operator
+ names. If you leave out the parenthesis here you will lose!
+ Currently 'o' 'p' CPLUS_MARKER is used for both the symbol in the
+ symbol-file and the names in gdb's symbol table.
+ Note that this macro is g++ specific (FIXME). */
+
+#define OPNAME_PREFIX_P(NAME) \
+ ((NAME)[0] == 'o' && (NAME)[1] == 'p' && (NAME)[2] == CPLUS_MARKER)
+
+/* Macro that yields non-zero value iff NAME is the prefix for C++ vtbl
+ names. Note that this macro is g++ specific (FIXME). */
+
+#define VTBL_PREFIX_P(NAME) \
+ ((NAME)[3] == CPLUS_MARKER && !strncmp ((NAME), "_vt", 3))
+
+/* Macro that yields non-zero value iff NAME is the prefix for C++ destructor
+ names. Note that this macro is g++ specific (FIXME). */
+
+#define DESTRUCTOR_PREFIX_P(NAME) \
+ ((NAME)[0] == '_' && (NAME)[1] == CPLUS_MARKER && (NAME)[2] == '_')
+
+
+/* External variables and functions for the objects described above. */
+
+/* This symtab variable specifies the current file for printing source lines */
+
+extern struct symtab *current_source_symtab;
+
+/* This is the next line to print for listing source lines. */
+
+extern int current_source_line;
+
+/* See the comment in symfile.c about how current_objfile is used. */
+
+extern struct objfile *current_objfile;
+
+extern struct symtab *
+lookup_symtab PARAMS ((char *));
+
+extern struct symbol *
+lookup_symbol PARAMS ((const char *, const struct block *,
+ const enum namespace, int *, struct symtab **));
+
+extern struct symbol *
+lookup_block_symbol PARAMS ((const struct block *, const char *,
+ const enum namespace));
+
+extern struct type *
+lookup_struct PARAMS ((char *, struct block *));
+
+extern struct type *
+lookup_union PARAMS ((char *, struct block *));
+
+extern struct type *
+lookup_enum PARAMS ((char *, struct block *));
+
+extern struct symbol *
+block_function PARAMS ((struct block *));
+
+extern struct symbol *
+find_pc_function PARAMS ((CORE_ADDR));
+
+extern int find_pc_partial_function
+ PARAMS ((CORE_ADDR, char **, CORE_ADDR *, CORE_ADDR *));
+
+extern void
+clear_pc_function_cache PARAMS ((void));
+
+extern struct partial_symtab *
+lookup_partial_symtab PARAMS ((char *));
+
+extern struct partial_symtab *
+find_pc_psymtab PARAMS ((CORE_ADDR));
+
+extern struct symtab *
+find_pc_symtab PARAMS ((CORE_ADDR));
+
+extern struct partial_symbol *
+find_pc_psymbol PARAMS ((struct partial_symtab *, CORE_ADDR));
+
+extern int
+find_pc_line_pc_range PARAMS ((CORE_ADDR, CORE_ADDR *, CORE_ADDR *));
+
+extern int
+contained_in PARAMS ((struct block *, struct block *));
+
+extern void
+reread_symbols PARAMS ((void));
+
+/* Functions for dealing with the minimal symbol table, really a misc
+ address<->symbol mapping for things we don't have debug symbols for. */
+
+extern void
+prim_record_minimal_symbol PARAMS ((const char *, CORE_ADDR,
+ enum minimal_symbol_type));
+
+extern void
+prim_record_minimal_symbol_and_info PARAMS ((const char *, CORE_ADDR,
+ enum minimal_symbol_type,
+ char *info, int section));
+
+extern struct minimal_symbol *
+lookup_minimal_symbol PARAMS ((const char *, struct objfile *));
+
+extern struct minimal_symbol *
+lookup_minimal_symbol_by_pc PARAMS ((CORE_ADDR));
+
+extern void
+init_minimal_symbol_collection PARAMS ((void));
+
+extern void
+discard_minimal_symbols PARAMS ((int));
+
+extern void
+install_minimal_symbols PARAMS ((struct objfile *));
+
+struct symtab_and_line
+{
+ struct symtab *symtab;
+
+ /* Line number. Line numbers start at 1 and proceed through symtab->nlines.
+ 0 is never a valid line number; it is used to indicate that line number
+ information is not available. */
+ 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. */
+
+extern struct symtab_and_line
+find_pc_line PARAMS ((CORE_ADDR, int));
+
+/* Given a symtab and line number, return the pc there. */
+
+extern CORE_ADDR
+find_line_pc PARAMS ((struct symtab *, int));
+
+extern int
+find_line_pc_range PARAMS ((struct symtab *, int, CORE_ADDR *, CORE_ADDR *));
+
+extern void
+resolve_sal_pc PARAMS ((struct symtab_and_line *));
+
+/* Given a string, return the line specified by it. For commands like "list"
+ and "breakpoint". */
+
+extern struct symtabs_and_lines
+decode_line_spec PARAMS ((char *, int));
+
+extern struct symtabs_and_lines
+decode_line_spec_1 PARAMS ((char *, int));
+
+extern struct symtabs_and_lines
+decode_line_1 PARAMS ((char **, int, struct symtab *, int, char ***));
+
+/* Symmisc.c */
+
+#if MAINTENANCE_CMDS
+
+void
+maintenance_print_symbols PARAMS ((char *, int));
+
+void
+maintenance_print_psymbols PARAMS ((char *, int));
+
+void
+maintenance_print_msymbols PARAMS ((char *, int));
+
+void
+maintenance_print_objfiles PARAMS ((char *, int));
+
+#endif
+
+extern void
+free_symtab PARAMS ((struct symtab *));
+
+/* Symbol-reading stuff in symfile.c and solib.c. */
+
+extern struct symtab *
+psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+extern void
+clear_solib PARAMS ((void));
+
+extern struct objfile *
+symbol_file_add PARAMS ((char *, int, CORE_ADDR, int, int, int));
+
+/* source.c */
+
+extern int frame_file_full_name; /* in stack.c */
+
+extern int
+identify_source_line PARAMS ((struct symtab *, int, int, CORE_ADDR));
+
+extern void
+print_source_lines PARAMS ((struct symtab *, int, int, int));
+
+extern void
+forget_cached_source_info PARAMS ((void));
+
+extern void
+select_source_symtab PARAMS ((struct symtab *));
+
+extern char **make_symbol_completion_list PARAMS ((char *, char *));
+
+/* symtab.c */
+
+extern struct partial_symtab *
+find_main_psymtab PARAMS ((void));
+
+/* blockframe.c */
+
+extern struct blockvector *
+blockvector_for_pc PARAMS ((CORE_ADDR, int *));
+
+/* symfile.c */
+
+extern void
+clear_symtab_users PARAMS ((void));
+
+extern enum language
+deduce_language_from_filename PARAMS ((char *));
+
+#endif /* !defined(SYMTAB_H) */
diff --git a/gnu/usr.bin/gdb/gdb/target.c b/gnu/usr.bin/gdb/gdb/target.c
new file mode 100644
index 000000000000..ea1bd93ca3b6
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/target.c
@@ -0,0 +1,789 @@
+/* Select target systems and architectures at runtime for GDB.
+ Copyright 1990, 1992, 1993 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <errno.h>
+#include <ctype.h>
+#include "target.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+extern int errno;
+
+static void
+target_info PARAMS ((char *, int));
+
+static void
+cleanup_target PARAMS ((struct target_ops *));
+
+static void
+maybe_kill_then_create_inferior PARAMS ((char *, char *, char **));
+
+static void
+maybe_kill_then_attach PARAMS ((char *, int));
+
+static void
+kill_or_be_killed PARAMS ((int));
+
+static void
+default_terminal_info PARAMS ((char *, int));
+
+static int
+nosymbol PARAMS ((char *, CORE_ADDR *));
+
+static void
+tcomplain PARAMS ((void));
+
+static int
+nomemory PARAMS ((CORE_ADDR, char *, int, int));
+
+static int
+return_zero PARAMS ((void));
+
+static void
+ignore PARAMS ((void));
+
+static void
+target_command PARAMS ((char *, int));
+
+static struct target_ops *
+find_default_run_target PARAMS ((char *));
+
+/* 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, /* open, close */
+ find_default_attach, 0, /* attach, detach */
+ 0, 0, /* resume, wait */
+ 0, 0, 0, /* registers */
+ 0, 0, /* memory */
+ 0, 0, /* bkpts */
+ 0, 0, 0, 0, 0, /* terminal */
+ 0, 0, /* kill, load */
+ 0, /* lookup_symbol */
+ find_default_create_inferior, /* create_inferior */
+ 0, /* mourn_inferior */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ dummy_stratum, 0, /* stratum, next */
+ 0, 0, 0, 0, 0, /* all mem, mem, stack, regs, exec */
+ 0, 0, /* section pointers */
+ 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;
+
+/* Command list for target. */
+
+static struct cmd_list_element *targetlist = NULL;
+
+/* The user just typed 'target' without the name of a target. */
+
+/* ARGSUSED */
+static void
+target_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ fputs_filtered ("Argument required (target name). Try `help target'\n",
+ stdout);
+}
+
+/* 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 ((char *) target_structs,
+ target_struct_allocsize * sizeof (*target_structs));
+ }
+ target_structs[target_struct_size++] = t;
+ cleanup_target (t);
+
+ if (targetlist == NULL)
+ add_prefix_cmd ("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.\n\
+Remaining arguments are interpreted by the target protocol. For more\n\
+information on the arguments for a particular protocol, type\n\
+`help target ' followed by the protocol name.",
+ &targetlist, "target ", 0, &cmdlist);
+ add_cmd (t->to_shortname, no_class, t->to_open, t->to_doc, &targetlist);
+}
+
+/* Stub functions */
+
+static void
+ignore ()
+{
+}
+
+/* ARGSUSED */
+static int
+nomemory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+ errno = EIO; /* Can't read/write this location */
+ return 0; /* No bytes handled */
+}
+
+static void
+tcomplain ()
+{
+ error ("You can't do that when your target is `%s'",
+ current_target->to_shortname);
+}
+
+void
+noprocess ()
+{
+ error ("You can't do that without a process to debug");
+}
+
+/* ARGSUSED */
+static int
+nosymbol (name, addrp)
+ char *name;
+ CORE_ADDR *addrp;
+{
+ return 1; /* Symbol does not exist in target env */
+}
+
+/* ARGSUSED */
+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;
+{
+ if (target_has_execution)
+ {
+ printf ("You are already running a program:\n");
+ target_files_info ();
+ if (query ("Kill it? ")) {
+ target_kill ();
+ 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, (void (*)())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, (int (*)())noprocess);
+ de_fault (to_fetch_registers, (void (*)())ignore);
+ de_fault (to_store_registers, (void (*)())noprocess);
+ de_fault (to_prepare_to_store, (void (*)())noprocess);
+ de_fault (to_xfer_memory, (int (*)())nomemory);
+ de_fault (to_files_info, (void (*)())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, (void (*)())tcomplain);
+ 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_can_run, return_zero);
+ de_fault (to_notice_signals, (void (*)())ignore);
+ 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 0
+ /* This will dump core if ever called--push_target expects current_target
+ to be non-NULL. But I don't think it's needed; I don't see how the
+ dummy_target could ever be removed from the stack. */
+ if (!current_target) /* At bottom, push dummy. */
+ push_target (&dummy_target);
+#endif
+}
+
+#undef MIN
+#define MIN(A, B) (((A) <= (B)) ? (A) : (B))
+
+/* target_read_string -- read a null terminated string from MEMADDR in target.
+ The read may also be terminated early by getting an error from target_xfer_
+ memory.
+ LEN is the size of the buffer pointed to by MYADDR. Note that a terminating
+ null will only be written if there is sufficient room. The return value is
+ is the number of bytes (including the null) actually transferred.
+*/
+
+int
+target_read_string (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int tlen, origlen, offset, i;
+ char buf[4];
+
+ origlen = len;
+
+ while (len > 0)
+ {
+ tlen = MIN (len, 4 - (memaddr & 3));
+ offset = memaddr & 3;
+
+ if (target_xfer_memory (memaddr & ~3, buf, 4, 0))
+ return origlen - len;
+
+ for (i = 0; i < tlen; i++)
+ {
+ *myaddr++ = buf[i + offset];
+ if (buf[i + offset] == '\000')
+ return (origlen - len) + i + 1;
+ }
+
+ memaddr += tlen;
+ len -= tlen;
+ }
+ return origlen;
+}
+
+/* Read LEN bytes of target memory at address MEMADDR, placing the results in
+ GDB's memory at MYADDR. Returns either 0 for success or an errno value
+ if any error occurs.
+
+ If an error occurs, no guarantee is made about the contents of the data at
+ MYADDR. In particular, the caller should not depend upon partial reads
+ filling the buffer with good data. There is no way for the caller to know
+ how much good data might have been transfered anyway. Callers that can
+ deal with partial reads should call target_read_memory_partial. */
+
+int
+target_read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ return target_xfer_memory (memaddr, myaddr, len, 0);
+}
+
+/* Read LEN bytes of target memory at address MEMADDR, placing the results
+ in GDB's memory at MYADDR. Returns a count of the bytes actually read,
+ and optionally an errno value in the location pointed to by ERRNOPTR
+ if ERRNOPTR is non-null. */
+
+int
+target_read_memory_partial (memaddr, myaddr, len, errnoptr)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int *errnoptr;
+{
+ int nread; /* Number of bytes actually read. */
+ int errcode; /* Error from last read. */
+
+ /* First try a complete read. */
+ errcode = target_xfer_memory (memaddr, myaddr, len, 0);
+ if (errcode == 0)
+ {
+ /* Got it all. */
+ nread = len;
+ }
+ else
+ {
+ /* Loop, reading one byte at a time until we get as much as we can. */
+ for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--)
+ {
+ errcode = target_xfer_memory (memaddr++, myaddr++, 1, 0);
+ }
+ /* If an error, the last read was unsuccessful, so adjust count. */
+ if (errcode != 0)
+ {
+ nread--;
+ }
+ }
+ if (errnoptr != NULL)
+ {
+ *errnoptr = errcode;
+ }
+ return (nread);
+}
+
+int
+target_write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ return target_xfer_memory (memaddr, myaddr, len, 1);
+}
+
+/* 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_xfer_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+ int curlen;
+ int res;
+ struct target_ops *t;
+
+ /* to_xfer_memory is not guaranteed to set errno, even when it returns
+ 0. */
+ errno = 0;
+
+ /* The quick case is that the top target does it all. */
+ res = current_target->to_xfer_memory
+ (memaddr, myaddr, len, write, current_target);
+ 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, t);
+ 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)
+ memset (myaddr, 0, len);
+ if (errno == 0)
+ return EIO;
+ else
+ return errno;
+ }
+bump:
+ memaddr += res;
+ myaddr += res;
+ len -= res;
+ }
+ return 0; /* We managed to cover it all somehow. */
+}
+
+
+/* ARGSUSED */
+static void
+target_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct target_ops *t;
+ int has_all_mem = 0;
+
+ if (symfile_objfile != NULL)
+ printf ("Symbols from \"%s\".\n", symfile_objfile->name);
+
+#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)(t);
+ has_all_mem = t->to_has_all_memory;
+ }
+}
+
+/* This is to be called by the open routine before it does
+ anything. */
+
+void
+target_preopen (from_tty)
+ int from_tty;
+{
+ dont_repeat();
+
+ if (target_has_execution)
+ {
+ if (query ("A program is being debugged already. Kill it? "))
+ target_kill ();
+ else
+ error ("Program not killed.");
+ }
+}
+
+/* Detach a target after doing deferred register stores. */
+
+void
+target_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ /* Handle any optimized stores to the inferior. */
+#ifdef DO_DEFERRED_STORES
+ DO_DEFERRED_STORES;
+#endif
+ (current_target->to_detach) (args, from_tty);
+}
+
+/* Look through the list of possible targets for a target that can
+ execute a run or attach command without any other data. This is
+ used to locate the default process stratum.
+
+ Result is always valid (error() is called for errors). */
+
+static struct target_ops *
+find_default_run_target (do_mesg)
+ char *do_mesg;
+{
+ struct target_ops **t;
+ struct target_ops *runable = NULL;
+ int count;
+
+ count = 0;
+
+ for (t = target_structs; t < target_structs + target_struct_size;
+ ++t)
+ {
+ if (target_can_run(*t))
+ {
+ runable = *t;
+ ++count;
+ }
+ }
+
+ if (count != 1)
+ error ("Don't know how to %s. Try \"help target\".", do_mesg);
+
+ return runable;
+}
+
+void
+find_default_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct target_ops *t;
+
+ t = find_default_run_target("attach");
+ (t->to_attach) (args, from_tty);
+ return;
+}
+
+void
+find_default_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ struct target_ops *t;
+
+ t = find_default_run_target("run");
+ (t->to_create_inferior) (exec_file, allargs, env);
+ return;
+}
+
+static int
+return_zero ()
+{
+ return 0;
+}
+
+struct target_ops *
+find_core_target ()
+{
+ struct target_ops **t;
+ struct target_ops *runable = NULL;
+ int count;
+
+ count = 0;
+
+ for (t = target_structs; t < target_structs + target_struct_size;
+ ++t)
+ {
+ if ((*t)->to_stratum == core_stratum)
+ {
+ runable = *t;
+ ++count;
+ }
+ }
+
+ return(count == 1 ? runable : NULL);
+}
+
+/* Convert a normal process ID to a string. Returns the string in a static
+ buffer. */
+
+char *
+normal_pid_to_str (pid)
+ int pid;
+{
+ static char buf[30];
+
+ sprintf (buf, "process %d", pid);
+
+ return buf;
+}
+
+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 ("target", target_info, targ_desc);
+ add_info ("files", target_info, targ_desc);
+}
diff --git a/gnu/usr.bin/gdb/gdb/target.h b/gnu/usr.bin/gdb/gdb/target.h
new file mode 100644
index 000000000000..c112b4ac122f
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/target.h
@@ -0,0 +1,465 @@
+/* Interface between GDB and target environments, including files and processes
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by John Gilmore.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (TARGET_H)
+#define TARGET_H
+
+/* 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. */
+
+#include "bfd.h"
+
+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 */
+ char *to_doc; /* Documentation. Does not include trailing
+ newline, and starts with a one-line descrip-
+ tion (probably similar to to_longname). */
+ void (*to_open) PARAMS ((char *, int));
+ void (*to_close) PARAMS ((int));
+ void (*to_attach) PARAMS ((char *, int));
+ void (*to_detach) PARAMS ((char *, int));
+ void (*to_resume) PARAMS ((int, int, int));
+ int (*to_wait) PARAMS ((int, int *));
+ void (*to_fetch_registers) PARAMS ((int));
+ void (*to_store_registers) PARAMS ((int));
+ void (*to_prepare_to_store) PARAMS ((void));
+
+ /* Transfer LEN bytes of memory between GDB address MYADDR and
+ target address MEMADDR. If WRITE, transfer them to the target, else
+ transfer them from the target. TARGET is the target from which we
+ get this function.
+
+ Return value, N, is one of the following:
+
+ 0 means that we can't handle this. If errno has been set, it is the
+ error which prevented us from doing it (FIXME: What about bfd_error?).
+
+ positive (call it N) means that we have transferred N bytes
+ starting at MEMADDR. We might be able to handle more bytes
+ beyond this length, but no promises.
+
+ negative (call its absolute value N) means that we cannot
+ transfer right at MEMADDR, but we could transfer at least
+ something at MEMADDR + N. */
+
+ int (*to_xfer_memory) PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len, int write,
+ struct target_ops * target));
+
+ void (*to_files_info) PARAMS ((struct target_ops *));
+ int (*to_insert_breakpoint) PARAMS ((CORE_ADDR, char *));
+ int (*to_remove_breakpoint) PARAMS ((CORE_ADDR, char *));
+ void (*to_terminal_init) PARAMS ((void));
+ void (*to_terminal_inferior) PARAMS ((void));
+ void (*to_terminal_ours_for_output) PARAMS ((void));
+ void (*to_terminal_ours) PARAMS ((void));
+ void (*to_terminal_info) PARAMS ((char *, int));
+ void (*to_kill) PARAMS ((void));
+ void (*to_load) PARAMS ((char *, int));
+ int (*to_lookup_symbol) PARAMS ((char *, CORE_ADDR *));
+ void (*to_create_inferior) PARAMS ((char *, char *, char **));
+ void (*to_mourn_inferior) PARAMS ((void));
+ int (*to_can_run) PARAMS ((void));
+ void (*to_notice_signals) PARAMS ((int pid));
+ 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;
+ struct section_table
+ *to_sections;
+ struct section_table
+ *to_sections_end;
+ int to_magic;
+ /* Need sub-structure for target machine related rather than comm related? */
+};
+
+/* 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. This should
+ never be NULL. If there is no target, it points to the dummy_target. */
+
+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)
+
+/* The open routine takes the rest of the parameters from the command,
+ and (if successful) pushes a new target onto the stack.
+ Targets should supply this routine, if only to provide an error message. */
+#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. Arguments are as passed
+ to the `attach' command by the user. This routine can be called
+ when the target is not on the target-stack, if the target_can_run
+ routine returns 1; in that case, it must push itself onto the stack.
+ Upon exit, the target should be ready for normal operations, and
+ should be ready to deliver the status of the process immediately
+ (without waiting) to an upcoming target_wait call. */
+
+#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. */
+
+extern void
+target_detach PARAMS ((char *, int));
+
+/* Resume execution of the target process PID. 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(pid, step, siggnal) \
+ (*current_target->to_resume) (pid, step, siggnal)
+
+/* Wait for process pid to do something. Pid = -1 to wait for any pid to do
+ something. Return pid of child, or -1 in case of error; store status
+ through argument pointer STATUS. */
+
+#define target_wait(pid, status) \
+ (*current_target->to_wait) (pid, status)
+
+/* Fetch register REGNO, or all regs if regno == -1. No result. */
+
+#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 target_prepare_to_store
+ must have been previously called. Calls error() if there are 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) ()
+
+extern int
+target_read_string PARAMS ((CORE_ADDR, char *, int));
+
+extern int
+target_read_memory PARAMS ((CORE_ADDR, char *, int));
+
+extern int
+target_read_memory_partial PARAMS ((CORE_ADDR, char *, int, int *));
+
+extern int
+target_write_memory PARAMS ((CORE_ADDR, char *, int));
+
+extern int
+xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+extern int
+child_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+/* Transfer LEN bytes between target address MEMADDR and GDB address MYADDR.
+ Returns 0 for success, errno code for failure (which includes partial
+ transfers--if you want a more useful response to partial transfers, try
+ target_read_memory_partial). */
+
+extern int target_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len, int write));
+
+/* From exec.c */
+
+extern void
+print_section_info PARAMS ((struct target_ops *, bfd *));
+
+/* Print a line about the current target. */
+
+#define target_files_info() \
+ (*current_target->to_files_info) (current_target)
+
+/* 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() \
+ (*current_target->to_kill) ()
+
+/* 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)
+
+/* 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) ()
+
+/* Does target have enough data to do a run or attach command? */
+
+#define target_can_run(t) \
+ ((t)->to_can_run) ()
+
+/* post process changes to signal handling in the inferior. */
+
+#define target_notice_signals(pid) \
+ (*current_target->to_notice_signals) (pid)
+
+/* 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? FIXME: If this is to work that
+ way, it needs to check whether an inferior actually exists.
+ remote-udi.c and probably other targets can be the current target
+ when the inferior doesn't actually exist at the moment. Right now
+ this just tells us whether this target is *capable* of execution. */
+
+#define target_has_execution \
+ (current_target->to_has_execution)
+
+/* Converts a process id to a string. Usually, the string just contains
+ `process xyz', but on some systems it may contain
+ `process xyz thread abc'. */
+
+#ifndef target_pid_to_str
+#define target_pid_to_str(PID) \
+ normal_pid_to_str (PID)
+extern char *normal_pid_to_str PARAMS ((int pid));
+#endif
+
+/* 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. */
+
+extern void
+add_target PARAMS ((struct target_ops *));
+
+extern int
+push_target PARAMS ((struct target_ops *));
+
+extern int
+unpush_target PARAMS ((struct target_ops *));
+
+extern void
+target_preopen PARAMS ((int));
+
+extern void
+pop_target PARAMS ((void));
+
+/* 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 */
+ bfd *bfd; /* BFD file pointer */
+};
+
+/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
+ Returns 0 if OK, 1 on error. */
+
+extern int
+build_section_table PARAMS ((bfd *, struct section_table **,
+ struct section_table **));
+
+/* From mem-break.c */
+
+extern int
+memory_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+extern int
+memory_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+/* From target.c */
+
+void
+noprocess PARAMS ((void));
+
+void
+find_default_attach PARAMS ((char *, int));
+
+void
+find_default_create_inferior PARAMS ((char *, char *, char **));
+
+struct target_ops *
+find_core_target PARAMS ((void));
+
+#endif /* !defined (TARGET_H) */
diff --git a/gnu/usr.bin/gdb/gdb/terminal.h b/gnu/usr.bin/gdb/gdb/terminal.h
new file mode 100644
index 000000000000..f76fa9031336
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/terminal.h
@@ -0,0 +1,62 @@
+/* Terminal interface definitions for GDB, the GNU Debugger.
+ Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (TERMINAL_H)
+#define TERMINAL_H 1
+
+#if !defined(__GO32__) && !defined (HAVE_TERMIOS)
+
+/* Define a common set of macros -- BSD based -- and redefine whatever
+ the system offers to make it look like that. FIXME: serial.h and
+ ser-*.c deal with this in a much cleaner fashion; as soon as stuff
+ is converted to use them, can get rid of this crap. */
+
+#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
+
+#else /* sgtty */
+
+#include <fcntl.h>
+#include <sgtty.h>
+#include <sys/ioctl.h>
+#define TERMINAL struct sgttyb
+
+#endif /* sgtty */
+#endif /* termio or sgtty */
+
+extern void new_tty PARAMS ((void));
+
+/* Do we have job control? Can be assumed to always be the same within
+ a given run of GDB. In inflow.c. */
+extern int job_control;
+
+/* Set the process group of the caller to its own pid, or do nothing if
+ we lack job control. */
+extern int gdb_setpgid PARAMS ((void));
+
+#endif /* !defined (TERMINAL_H) */
diff --git a/gnu/usr.bin/gdb/gdb/thread.c b/gnu/usr.bin/gdb/gdb/thread.c
new file mode 100644
index 000000000000..f14b41fc041c
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/thread.c
@@ -0,0 +1,248 @@
+/* Multi-process/thread control for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1993
+
+ Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+#include "target.h"
+#include "thread.h"
+#include "command.h"
+
+#include <sys/types.h>
+#include <signal.h>
+
+/*#include "lynxos-core.h"*/
+
+struct thread_info
+{
+ struct thread_info *next;
+ int pid; /* Actual process id */
+ int num; /* Convenient handle */
+};
+
+static struct thread_info *thread_list = NULL;
+static int highest_thread_num;
+
+static void thread_command PARAMS ((char * tidstr, int from_tty));
+
+static void prune_threads PARAMS ((void));
+
+static void thread_switch PARAMS ((int pid));
+
+static struct thread_info * find_thread_id PARAMS ((int num));
+
+void
+init_thread_list ()
+{
+ struct thread_info *tp, *tpnext;
+
+ if (!thread_list)
+ return;
+
+ for (tp = thread_list; tp; tp = tpnext)
+ {
+ tpnext = tp->next;
+ free (tp);
+ }
+
+ thread_list = NULL;
+ highest_thread_num = 0;
+}
+
+void
+add_thread (pid)
+ int pid;
+{
+ struct thread_info *tp;
+
+ tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
+
+ tp->pid = pid;
+ tp->num = ++highest_thread_num;
+ tp->next = thread_list;
+ thread_list = tp;
+}
+
+static struct thread_info *
+find_thread_id (num)
+ int num;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->num == num)
+ return tp;
+
+ return NULL;
+}
+
+int
+valid_thread_id (num)
+ int num;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->num == num)
+ return 1;
+
+ return 0;
+}
+
+int
+pid_to_thread_id (pid)
+ int pid;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->pid == pid)
+ return tp->num;
+
+ return 0;
+}
+
+int
+in_thread_list (pid)
+ int pid;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->pid == pid)
+ return 1;
+
+ return 0; /* Never heard of 'im */
+}
+
+static void
+prune_threads ()
+{
+ struct thread_info *tp, *tpprev;
+
+ tpprev = 0;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->pid == -1)
+ {
+ if (tpprev)
+ tpprev->next = tp->next;
+ else
+ thread_list = NULL;
+
+ free (tp);
+ }
+ else
+ tpprev = tp;
+}
+
+/* Print information about currently known threads */
+
+static void
+info_threads_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct thread_info *tp;
+ int current_pid = inferior_pid;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ {
+ if (target_has_execution
+ && kill (tp->pid, 0) == -1)
+ {
+ tp->pid = -1; /* Mark it as dead */
+ continue;
+ }
+
+ if (tp->pid == current_pid)
+ printf_filtered ("* ");
+ else
+ printf_filtered (" ");
+
+ printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
+
+ thread_switch (tp->pid);
+ print_stack_frame (selected_frame, -1, 0);
+ }
+
+ thread_switch (current_pid);
+ prune_threads ();
+}
+
+/* Switch from one thread to another. */
+
+static void
+thread_switch (pid)
+ int pid;
+{
+ if (pid == inferior_pid)
+ return;
+
+ inferior_pid = pid;
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc();
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ stop_frame_address = FRAME_FP (get_current_frame ());
+ select_frame (get_current_frame (), 0);
+}
+
+static void
+thread_command (tidstr, from_tty)
+ char *tidstr;
+ int from_tty;
+{
+ int num;
+ struct thread_info *tp;
+
+ if (!tidstr)
+ error ("Please specify a thread ID. Use the \"info threads\" command to\n\
+see the IDs of currently known threads.");
+
+
+ num = atoi (tidstr);
+
+ tp = find_thread_id (num);
+
+ if (!tp)
+ error ("Thread ID %d not known. Use the \"info threads\" command to\n\
+see the IDs of currently known threads.", num);
+
+ thread_switch (tp->pid);
+
+ printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+void
+_initialize_thread ()
+{
+ add_info ("threads", info_threads_command,
+ "IDs of currently known threads.");
+ add_com ("thread", class_info, thread_command,
+ "Use this command to switch between threads.\n\
+The new thread ID must be currently known.");
+}
diff --git a/gnu/usr.bin/gdb/gdb/thread.h b/gnu/usr.bin/gdb/gdb/thread.h
new file mode 100644
index 000000000000..2ec94fc5c5e4
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/thread.h
@@ -0,0 +1,36 @@
+/* Multi-process/thread control defs for GDB, the GNU debugger.
+ Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993
+
+ Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
+ Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef THREAD_H
+#define THREAD_H
+
+extern void init_thread_list PARAMS ((void));
+
+extern void add_thread PARAMS ((int pid));
+
+extern int in_thread_list PARAMS ((int pid));
+
+extern int pid_to_thread_id PARAMS ((int pid));
+
+extern int valid_thread_id PARAMS ((int thread));
+
+#endif /* THREAD_H */
diff --git a/gnu/usr.bin/gdb/config/m-i386.h b/gnu/usr.bin/gdb/gdb/tm-i386v.h
index 5449ec454c95..f80f51921488 100644
--- a/gnu/usr.bin/gdb/config/m-i386.h
+++ b/gnu/usr.bin/gdb/gdb/tm-i386v.h
@@ -1,90 +1,42 @@
-/* Macro defintions for i386.
- Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+/* Macro definitions for i386, Unix System V.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
This file is part of GDB.
-GDB is free software; you can redistribute it and/or modify
+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.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* Define the bit, byte, and word ordering of the machine. */
-/* #define BITS_BIG_ENDIAN */
-/* #define BYTES_BIG_ENDIAN */
-/* #define WORDS_BIG_ENDIAN */
+#if !defined (TM_I386V_H)
+#define TM_I386V_H 1
/*
* Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu)
* July 1988
*/
-
-#ifndef i386
-#define i386
-#endif
-
-/* 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 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
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
/* turn this on when rest of gdb is ready */
-/* #define IEEE_FLOAT */
-
-#define NBPG NBPC
-#define UPAGES USIZE
-
-#define HAVE_TERMIO
-
-/* Get rid of any system-imposed stack limit if possible. */
-
-/* #define SET_STACK_LIMIT_HUGE not in sys5 */
-
-/* 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
+#define IEEE_FLOAT
/* 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.
*/
+#ifndef START_INFERIOR_TRAPS_EXPECTED
#define START_INFERIOR_TRAPS_EXPECTED 4
+#endif
/* Offset from address of function to start of its code.
Zero on most machines. */
@@ -96,6 +48,9 @@ on those where it does, it occurs quite reliably. */
#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
+extern int
+i386_skip_prologue PARAMS ((int));
+
/* 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
@@ -104,15 +59,6 @@ on those where it does, it occurs quite reliably. */
#define SAVED_PC_AFTER_CALL(frame) \
(read_memory_integer (read_register (SP_REGNUM), 4))
-/* 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
-
-/* Address of end of stack space. */
-
-#define STACK_END_ADDR 0x80000000
-
/* Stack grows downward. */
#define INNER_THAN <
@@ -125,7 +71,9 @@ on those where it does, it occurs quite reliably. */
This is often the number of bytes in BREAKPOINT
but not always. */
+#ifndef DECR_PC_AFTER_BREAK
#define DECR_PC_AFTER_BREAK 1
+#endif
/* Nonzero if instruction at PC is a return instruction. */
@@ -136,19 +84,6 @@ on those where it does, it occurs quite reliably. */
#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 (); }
-
-
-/* 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
@@ -183,9 +118,6 @@ on those where it does, it occurs quite reliably. */
#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)
@@ -221,31 +153,36 @@ on those where it does, it occurs quite reliably. */
/* 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);}
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
+ {memcpy ((TO), (FROM), 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);}
+#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
+ {memcpy ((TO), (FROM), 4);}
/* Return the GDB type object for the "standard" data type
of data in register N. */
-
-#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
+/* Perhaps si and di should go here, but potentially they could be
+ used for things other than address. */
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM ? \
+ lookup_pointer_type (builtin_type_void) : 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)); }
+ write_memory ((SP), (char *) &(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))
+ memcpy ((VALBUF), (REGBUF), TYPE_LENGTH (TYPE))
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
@@ -264,32 +201,20 @@ on those where it does, it occurs quite reliably. */
(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. */
+ and produces the frame's chain-pointer. */
#define FRAME_CHAIN(thisframe) \
- (outside_startup_file ((thisframe)->pc) ? \
+ (!inside_entry_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_LOOK_FOR_PROLOGUE(FI, FRAMELESS)
+ (FRAMELESS) = frameless_look_for_prologue(FI)
#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
@@ -300,7 +225,15 @@ on those where it does, it occurs quite reliably. */
/* 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)
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = -1
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct frame_info;
+struct frame_saved_regs;
+#endif
+
+extern int
+i386_frame_num_args PARAMS ((struct frame_info *));
/* Return number of bytes at start of arglist that are not really args. */
@@ -315,6 +248,10 @@ on those where it does, it occurs quite reliably. */
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+extern void
+i386_frame_find_saved_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+
/* Things needed for making the inferior call functions. */
@@ -322,10 +259,16 @@ on those where it does, it occurs quite reliably. */
#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
+extern void
+i386_push_dummy_frame PARAMS ((void));
+
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME { i386_pop_frame (); }
+extern void
+i386_pop_frame PARAMS ((void));
+
/* this is
* call 11223344 (32 bit relative)
* int3
@@ -340,55 +283,27 @@ on those where it does, it occurs quite reliably. */
/* 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) \
+#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; \
+ *((char *)(dummyname) + 1) = (delta & 0xff); \
+ *((char *)(dummyname) + 2) = ((delta >> 8) & 0xff); \
+ *((char *)(dummyname) + 3) = ((delta >> 16) & 0xff); \
+ *((char *)(dummyname) + 4) = ((delta >> 24) & 0xff); \
}
-
-#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}
+extern void
+print_387_control_word PARAMS ((unsigned int));
-/* 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. */
+extern void
+print_387_status_word PARAMS ((unsigned int));
-#define INIT_STACK(beg, end) {}
+/* Offset from SP to first arg on stack at first instruction of a function */
-/* Push the frame pointer register on the stack. */
-#define PUSH_FRAME_PTR {}
+#define SP_ARG0 (1 * 4)
-/* 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
+#endif /* !defined (TM_I386V_H) */
diff --git a/gnu/usr.bin/gdb/gdb/tm.h b/gnu/usr.bin/gdb/gdb/tm.h
new file mode 100644
index 000000000000..25b66c709dee
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/tm.h
@@ -0,0 +1,76 @@
+/* Macro definitions for i386 running under BSD Unix.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Override number of expected traps from sysv. */
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Most definitions from sysv could be used. */
+#include "tm-i386v.h"
+
+/* 386BSD cannot handle the segment registers. */
+/* BSDI can't handle them either. */
+#undef NUM_REGS
+#define NUM_REGS 10
+
+/* On 386 bsd, sigtramp is above the user stack and immediately below
+ the user area. Using constants here allows for cross debugging.
+ These are tested for BSDI but should work on 386BSD. */
+#define SIGTRAMP_START 0xfdbfdfc0
+#define SIGTRAMP_END 0xfdbfe000
+
+/* The following redefines make backtracing through sigtramp work.
+ They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
+ from the sigcontext structure which is pushed by the kernel on the
+ user stack, along with a pointer to it. */
+
+/* FRAME_CHAIN takes a frame's nominal address and produces the frame's
+ chain-pointer.
+ In the case of the i386, the frame's nominal address
+ is the address of a 4-byte word containing the calling frame's address. */
+#undef FRAME_CHAIN
+#define FRAME_CHAIN(thisframe) \
+ (thisframe->signal_handler_caller \
+ ? thisframe->frame \
+ : (!inside_entry_file ((thisframe)->pc) \
+ ? read_memory_integer ((thisframe)->frame, 4) \
+ : 0))
+
+/* 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. */
+#undef FRAMELESS_FUNCTION_INVOCATION
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ do { \
+ if ((FI)->signal_handler_caller) \
+ (FRAMELESS) = 0; \
+ else \
+ (FRAMELESS) = frameless_look_for_prologue(FI); \
+ } while (0)
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+/* Offset to saved PC in sigcontext, from <sys/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 20
+
+#undef FRAME_SAVED_PC(FRAME)
+#define FRAME_SAVED_PC(FRAME) \
+ (((FRAME)->signal_handler_caller \
+ ? sigtramp_saved_pc (FRAME) \
+ : read_memory_integer ((FRAME)->frame + 4, 4)) \
+ )
diff --git a/gnu/usr.bin/gdb/gdb/typeprint.c b/gnu/usr.bin/gdb/gdb/typeprint.c
new file mode 100644
index 000000000000..5e13e07fb4d9
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/typeprint.c
@@ -0,0 +1,297 @@
+/* Language independent support for printing types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "language.h"
+#include "demangle.h"
+
+#include <string.h>
+#include <errno.h>
+
+static void
+ptype_command PARAMS ((char *, int));
+
+static struct type *
+ptype_eval PARAMS ((struct expression *));
+
+static void
+whatis_command PARAMS ((char *, int));
+
+static void
+whatis_exp PARAMS ((char *, int));
+
+/* 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;
+{
+ LA_PRINT_TYPE (type, varstring, stream, show, 0);
+}
+
+/* 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 = NULL;
+
+ if (exp)
+ {
+ expr = parse_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);
+}
+
+/* ARGSUSED */
+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);
+}
+
+/* Simple subroutine for ptype_command. */
+
+static struct type *
+ptype_eval (exp)
+ struct expression *exp;
+{
+ if (exp->elts[0].opcode == OP_TYPE)
+ {
+ return (exp->elts[1].type);
+ }
+ else
+ {
+ return (NULL);
+ }
+}
+
+/* TYPENAME is either the name of a type, or an expression. */
+
+/* ARGSUSED */
+static void
+ptype_command (typename, from_tty)
+ char *typename;
+ int from_tty;
+{
+ register struct type *type;
+ struct expression *expr;
+ register struct cleanup *old_chain;
+
+ if (typename == NULL)
+ {
+ /* Print type of last thing in value history. */
+ whatis_exp (typename, 1);
+ }
+ else
+ {
+ expr = parse_expression (typename);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ type = ptype_eval (expr);
+ if (type != NULL)
+ {
+ /* User did "ptype <typename>" */
+ printf_filtered ("type = ");
+ type_print (type, "", stdout, 1);
+ printf_filtered ("\n");
+ do_cleanups (old_chain);
+ }
+ else
+ {
+ /* User did "ptype <symbolname>" */
+ do_cleanups (old_chain);
+ whatis_exp (typename, 1);
+ }
+ }
+}
+
+/* Print integral scalar data VAL, of type TYPE, onto stdio stream STREAM.
+ Used to print data from type structures in a specified type. For example,
+ array bounds may be characters or booleans in some languages, and this
+ allows the ranges to be printed in their "natural" form rather than as
+ decimal integer values.
+
+ FIXME: This is here simply because only the type printing routines
+ currently use it, and it wasn't clear if it really belonged somewhere
+ else (like printcmd.c). There are a lot of other gdb routines that do
+ something similar, but they are generally concerned with printing values
+ that come from the inferior in target byte order and target size. */
+
+void
+print_type_scalar (type, val, stream)
+ struct type *type;
+ LONGEST val;
+ FILE *stream;
+{
+ unsigned int i;
+ unsigned len;
+
+ switch (TYPE_CODE (type))
+ {
+
+ case TYPE_CODE_ENUM:
+ len = TYPE_NFIELDS (type);
+ for (i = 0; i < len; i++)
+ {
+ if (TYPE_FIELD_BITPOS (type, i) == val)
+ {
+ break;
+ }
+ }
+ if (i < len)
+ {
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+ }
+ else
+ {
+ print_longest (stream, 'd', 0, val);
+ }
+ break;
+
+ case TYPE_CODE_INT:
+ print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0, val);
+ break;
+
+ case TYPE_CODE_CHAR:
+ LA_PRINT_CHAR ((unsigned char) val, stream);
+ break;
+
+ case TYPE_CODE_BOOL:
+ fprintf_filtered (stream, val ? "TRUE" : "FALSE");
+ break;
+
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_REF:
+ error ("internal error: unhandled type in print_type_scalar");
+ break;
+
+ default:
+ error ("Invalid type code in symbol table.");
+ }
+ fflush (stream);
+}
+
+#if MAINTENANCE_CMDS
+
+/* Dump details of a type specified either directly or indirectly.
+ Uses the same sort of type lookup mechanism as ptype_command()
+ and whatis_command(). */
+
+void
+maintenance_print_type (typename, from_tty)
+ char *typename;
+ int from_tty;
+{
+ register value val;
+ register struct type *type;
+ register struct cleanup *old_chain;
+ struct expression *expr;
+
+ if (typename != NULL)
+ {
+ expr = parse_expression (typename);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ if (expr -> elts[0].opcode == OP_TYPE)
+ {
+ /* The user expression names a type directly, just use that type. */
+ type = expr -> elts[1].type;
+ }
+ else
+ {
+ /* The user expression may name a type indirectly by naming an
+ object of that type. Find that indirectly named type. */
+ val = evaluate_type (expr);
+ type = VALUE_TYPE (val);
+ }
+ if (type != NULL)
+ {
+ recursive_dump_type (type, 0);
+ }
+ do_cleanups (old_chain);
+ }
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+
+void
+_initialize_typeprint ()
+{
+
+ 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.");
+
+}
diff --git a/gnu/usr.bin/gdb/gdb/typeprint.h b/gnu/usr.bin/gdb/gdb/typeprint.h
new file mode 100644
index 000000000000..e6740db7c298
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/typeprint.h
@@ -0,0 +1,21 @@
+/* Language independent support for printing types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+void
+print_type_scalar PARAMS ((struct type *type, LONGEST, FILE *));
diff --git a/gnu/usr.bin/gdb/gdb/utils.c b/gnu/usr.bin/gdb/gdb/utils.c
new file mode 100644
index 000000000000..38010e323e6f
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/utils.c
@@ -0,0 +1,1547 @@
+/* General utility routines for GDB, the GNU debugger.
+ Copyright 1986, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#if !defined(__GO32__)
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <pwd.h>
+#endif
+#include <varargs.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "signals.h"
+#include "gdbcmd.h"
+#include "serial.h"
+#include "terminal.h" /* For job_control */
+#include "bfd.h"
+#include "target.h"
+#include "demangle.h"
+#include "expression.h"
+#include "language.h"
+
+/* Prototypes for local functions */
+
+#if defined (NO_MMALLOC) || defined (NO_MMALLOC_CHECK)
+#else
+
+static void
+malloc_botch PARAMS ((void));
+
+#endif /* NO_MMALLOC, etc */
+
+static void
+fatal_dump_core (); /* Can't prototype with <varargs.h> usage... */
+
+static void
+prompt_for_continue PARAMS ((void));
+
+static void
+set_width_command PARAMS ((char *, int, struct cmd_list_element *));
+
+/* 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
+
+/* 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. Be careful in setting this;
+ code which executes with immediate_quit set has to be very careful
+ about being able to deal with being interrupted at any time. It is
+ almost always better to use QUIT; the only exception I can think of
+ is being able to quit out of a system call (using EINTR loses if
+ the SIGINT happens between the previous QUIT and the system call).
+ To immediately quit in the case in which a SIGINT happens between
+ the previous QUIT and setting immediate_quit (desirable anytime we
+ expect to block), call QUIT after setting immediate_quit. */
+
+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;
+
+/* String to be printed before error messages, if any. */
+
+char *error_pre_print;
+char *warning_pre_print = "\nwarning: ";
+
+/* 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) PARAMS ((PTR));
+ PTR 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)
+ {
+ cleanup_chain = ptr->next; /* Do this first incase recursion */
+ (*ptr->function) (ptr->arg);
+ 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)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);
+}
+
+/* Provide a known function that does nothing, to use as a base for
+ for a possibly long chain of cleanups. This is useful where we
+ use the cleanup chain for handling normal cleanups as well as dealing
+ with cleanups that need to be done as a result of a call to error().
+ In such cases, we may not be certain where the first cleanup is, unless
+ we have a do-nothing one to always use as the base. */
+
+/* ARGSUSED */
+void
+null_cleanup (arg)
+ char **arg;
+{
+}
+
+
+/* Provide a hook for modules wishing to print their own warning messages
+ to set up the terminal state in a compatible way, without them having
+ to import all the target_<...> macros. */
+
+void
+warning_setup ()
+{
+ target_terminal_ours ();
+ wrap_here(""); /* Force out any buffered output */
+ fflush (stdout);
+}
+
+/* Print a warning message.
+ The first argument STRING is the warning message, used as a fprintf string,
+ and the remaining args are passed as arguments to it.
+ The primary difference between warnings and errors is that a warning
+ does not force the return to command level. */
+
+/* VARARGS */
+void
+warning (va_alist)
+ va_dcl
+{
+ va_list args;
+ char *string;
+
+ va_start (args);
+ target_terminal_ours ();
+ wrap_here(""); /* Force out any buffered output */
+ fflush (stdout);
+ if (warning_pre_print)
+ fprintf (stderr, warning_pre_print);
+ string = va_arg (args, char *);
+ vfprintf (stderr, string, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+}
+
+/* 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 */
+NORETURN void
+error (va_alist)
+ va_dcl
+{
+ va_list args;
+ char *string;
+
+ va_start (args);
+ target_terminal_ours ();
+ wrap_here(""); /* Force out any buffered output */
+ fflush (stdout);
+ if (error_pre_print)
+ fprintf_filtered (stderr, error_pre_print);
+ string = va_arg (args, char *);
+ vfprintf_filtered (stderr, string, args);
+ fprintf_filtered (stderr, "\n");
+ va_end (args);
+ return_to_top_level (RETURN_ERROR);
+}
+
+/* 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.
+
+ This function cannot be declared volatile (NORETURN) in an
+ ANSI environment because exit() is not declared volatile. */
+
+/* VARARGS */
+NORETURN void
+fatal (va_alist)
+ va_dcl
+{
+ va_list args;
+ char *string;
+
+ va_start (args);
+ string = va_arg (args, char *);
+ fprintf (stderr, "\ngdb: ");
+ 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 */
+static 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, "\ngdb 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);
+}
+
+/* The strerror() function can return NULL for errno values that are
+ out of range. Provide a "safe" version that always returns a
+ printable string. */
+
+char *
+safe_strerror (errnum)
+ int errnum;
+{
+ char *msg;
+ static char buf[32];
+
+ if ((msg = strerror (errnum)) == NULL)
+ {
+ sprintf (buf, "(undocumented errno %d)", errnum);
+ msg = buf;
+ }
+ return (msg);
+}
+
+/* The strsignal() function can return NULL for signal values that are
+ out of range. Provide a "safe" version that always returns a
+ printable string. */
+
+char *
+safe_strsignal (signo)
+ int signo;
+{
+ char *msg;
+ static char buf[32];
+
+ if ((msg = strsignal (signo)) == NULL)
+ {
+ sprintf (buf, "(undocumented signal %d)", signo);
+ msg = buf;
+ }
+ return (msg);
+}
+
+
+/* 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;
+{
+ char *err;
+ char *combined;
+
+ err = safe_strerror (errno);
+ 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;
+{
+ char *err;
+ char *combined;
+
+ err = safe_strerror (errcode);
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ fprintf (stderr, "%s.\n", combined);
+}
+
+/* Control C eventually causes this to be called, at a convenient time. */
+
+void
+quit ()
+{
+ serial_t stdout_serial = serial_fdopen (1);
+
+ target_terminal_ours ();
+ wrap_here ((char *)0); /* Force out any pending output */
+
+ SERIAL_FLUSH_OUTPUT (stdout_serial);
+
+ SERIAL_UN_FDOPEN (stdout_serial);
+
+ /* Don't use *_filtered; we don't want to prompt the user to continue. */
+ if (error_pre_print)
+ fprintf (stderr, error_pre_print);
+
+ if (job_control
+ /* If there is no terminal switching for this target, then we can't
+ possibly get screwed by the lack of job control. */
+ || current_target->to_terminal_ours == NULL)
+ fprintf (stderr, "Quit\n");
+ else
+ fprintf (stderr,
+ "Quit (expect signal SIGINT when the program is resumed)\n");
+ return_to_top_level (RETURN_QUIT);
+}
+
+
+#ifdef __GO32__
+
+/* In the absence of signals, poll keyboard for a quit.
+ Called from #define QUIT pollquit() in xm-go32.h. */
+
+void
+pollquit()
+{
+ if (kbhit ())
+ {
+ int k = getkey ();
+ if (k == 1)
+ quit_flag = 1;
+ else if (k == 2)
+ immediate_quit = 1;
+ quit ();
+ }
+}
+
+#endif
+
+/* Control C comes here */
+
+void
+request_quit (signo)
+ int signo;
+{
+ quit_flag = 1;
+
+#ifdef USG
+ /* Restore the signal handler. */
+ signal (signo, request_quit);
+#endif
+
+ if (immediate_quit)
+ quit ();
+}
+
+
+/* Memory management stuff (malloc friends). */
+
+#if defined (NO_MMALLOC)
+
+PTR
+mmalloc (md, size)
+ PTR md;
+ long size;
+{
+ return (malloc (size));
+}
+
+PTR
+mrealloc (md, ptr, size)
+ PTR md;
+ PTR ptr;
+ long size;
+{
+ if (ptr == 0) /* Guard against old realloc's */
+ return malloc (size);
+ else
+ return realloc (ptr, size);
+}
+
+void
+mfree (md, ptr)
+ PTR md;
+ PTR ptr;
+{
+ free (ptr);
+}
+
+#endif /* NO_MMALLOC */
+
+#if defined (NO_MMALLOC) || defined (NO_MMALLOC_CHECK)
+
+void
+init_malloc (md)
+ PTR md;
+{
+}
+
+#else /* have mmalloc and want corruption checking */
+
+static void
+malloc_botch ()
+{
+ fatal_dump_core ("Memory corruption");
+}
+
+/* Attempt to install hooks in mmalloc/mrealloc/mfree for the heap specified
+ by MD, to detect memory corruption. Note that MD may be NULL to specify
+ the default heap that grows via sbrk.
+
+ Note that for freshly created regions, we must call mmcheck prior to any
+ mallocs in the region. Otherwise, any region which was allocated prior to
+ installing the checking hooks, which is later reallocated or freed, will
+ fail the checks! The mmcheck function only allows initial hooks to be
+ installed before the first mmalloc. However, anytime after we have called
+ mmcheck the first time to install the checking hooks, we can call it again
+ to update the function pointer to the memory corruption handler.
+
+ Returns zero on failure, non-zero on success. */
+
+void
+init_malloc (md)
+ PTR md;
+{
+ if (!mmcheck (md, malloc_botch))
+ {
+ warning ("internal error: failed to install memory consistency checks");
+ }
+
+ mmtrace ();
+}
+
+#endif /* Have mmalloc and want corruption checking */
+
+/* Called when a memory allocation fails, with the number of bytes of
+ memory requested in SIZE. */
+
+NORETURN void
+nomem (size)
+ long size;
+{
+ if (size > 0)
+ {
+ fatal ("virtual memory exhausted: can't allocate %ld bytes.", size);
+ }
+ else
+ {
+ fatal ("virtual memory exhausted.");
+ }
+}
+
+/* Like mmalloc but get error if no storage available, and protect against
+ the caller wanting to allocate zero bytes. Whether to return NULL for
+ a zero byte request, or translate the request into a request for one
+ byte of zero'd storage, is a religious issue. */
+
+PTR
+xmmalloc (md, size)
+ PTR md;
+ long size;
+{
+ register PTR val;
+
+ if (size == 0)
+ {
+ val = NULL;
+ }
+ else if ((val = mmalloc (md, size)) == NULL)
+ {
+ nomem (size);
+ }
+ return (val);
+}
+
+/* Like mrealloc but get error if no storage available. */
+
+PTR
+xmrealloc (md, ptr, size)
+ PTR md;
+ PTR ptr;
+ long size;
+{
+ register PTR val;
+
+ if (ptr != NULL)
+ {
+ val = mrealloc (md, ptr, size);
+ }
+ else
+ {
+ val = mmalloc (md, size);
+ }
+ if (val == NULL)
+ {
+ nomem (size);
+ }
+ return (val);
+}
+
+/* Like malloc but get error if no storage available, and protect against
+ the caller wanting to allocate zero bytes. */
+
+PTR
+xmalloc (size)
+ long size;
+{
+ return (xmmalloc ((PTR) NULL, size));
+}
+
+/* Like mrealloc but get error if no storage available. */
+
+PTR
+xrealloc (ptr, size)
+ PTR ptr;
+ long size;
+{
+ return (xmrealloc ((PTR) NULL, ptr, size));
+}
+
+
+/* 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;
+}
+
+/* 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)
+ const char *ptr;
+ int size;
+{
+ register char *p = (char *) xmalloc (size + 1);
+ memcpy (p, ptr, size);
+ p[size] = 0;
+ return p;
+}
+
+char *
+msavestring (md, ptr, size)
+ PTR md;
+ const char *ptr;
+ int size;
+{
+ register char *p = (char *) xmmalloc (md, size + 1);
+ memcpy (p, ptr, size);
+ p[size] = 0;
+ return p;
+}
+
+/* The "const" is so it compiles under DGUX (which prototypes strsave
+ in <string.h>. FIXME: This should be named "xstrsave", shouldn't it?
+ Doesn't real strsave return NULL if out of memory? */
+char *
+strsave (ptr)
+ const char *ptr;
+{
+ return savestring (ptr, strlen (ptr));
+}
+
+char *
+mstrsave (md, ptr)
+ PTR md;
+ const char *ptr;
+{
+ return (msavestring (md, ptr, strlen (ptr)));
+}
+
+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)
+ {
+ wrap_here (""); /* Flush any buffered output */
+ fflush (stdout);
+ va_start (args);
+ ctlstr = va_arg (args, char *);
+ vfprintf_filtered (stdout, ctlstr, args);
+ va_end (args);
+ printf_filtered ("(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_filtered ("Please answer y or n.\n");
+ }
+}
+
+
+/* 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 007; /* Bell (alert) char */
+ case 'b':
+ return '\b';
+ case 'e': /* Escape character */
+ 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;
+ }
+}
+
+/* Print the character C on STREAM as part of the contents of a literal
+ string whose delimiter is QUOTER. Note that this routine should only
+ be call for printing things which are independent of the language
+ of the program being debugged. */
+
+void
+gdb_printchar (c, stream, quoter)
+ register int c;
+ FILE *stream;
+ int quoter;
+{
+
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if ( c < 0x20 || /* Low control chars */
+ (c >= 0x7F && c < 0xA0) || /* DEL, High controls */
+ (sevenbit_strings && c >= 0x80)) { /* high order bit set */
+ 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);
+ }
+}
+
+/* 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. */
+
+/* Malloc'd buffer with chars_per_line+2 bytes. Contains characters which
+ are waiting to be output (they have already been counted in chars_printed).
+ When wrap_buffer[0] is null, the buffer is empty. */
+static char *wrap_buffer;
+
+/* Pointer in wrap_buffer to the next character to fill. */
+static char *wrap_pointer;
+
+/* String to indent by if the wrap occurs. Must not be NULL if wrap_column
+ is non-zero. */
+static char *wrap_indent;
+
+/* Column number on the screen where wrap_buffer begins, or 0 if wrapping
+ is not in effect. */
+static int wrap_column;
+
+/* ARGSUSED */
+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 */
+}
+
+/* Wait, so the user can read what's on the screen. Prompt the user
+ to continue by pressing RETURN. */
+
+static void
+prompt_for_continue ()
+{
+ char *ignore;
+
+ /* We must do this *before* we call gdb_readline, else it will eventually
+ call us -- thinking that we're trying to print beyond the end of the
+ screen. */
+ reinitialize_more_filter ();
+
+ immediate_quit++;
+ /* On a real operating system, the user can quit with SIGINT.
+ But not on GO32.
+
+ 'q' is provided on all systems so users don't have to change habits
+ from system to system, and because telling them what to do in
+ the prompt is more user-friendly than expecting them to think of
+ SIGINT. */
+ ignore =
+ gdb_readline ("---Type <return> to continue, or q <return> to quit---");
+ if (ignore)
+ {
+ char *p = ignore;
+ while (*p == ' ' || *p == '\t')
+ ++p;
+ if (p[0] == 'q')
+ request_quit (SIGINT);
+ free (ignore);
+ }
+ immediate_quit--;
+
+ /* Now we have to do this again, so that GDB will know that it doesn't
+ need to save the ---Type <return>--- line at the top of the screen. */
+ reinitialize_more_filter ();
+
+ dont_repeat (); /* Forget prev cmd -- CR won't repeat it. */
+}
+
+/* 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 non-null, 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.
+
+ If we don't know the width of lines, but we know the page height,
+ we must not wrap words, but should still keep track of newlines
+ that were explicitly printed.
+
+ INDENT should not contain tabs, as that will mess up the char count
+ on the next line. FIXME.
+
+ This routine is guaranteed to force out any output which has been
+ squirreled away in the wrap_buffer, so wrap_here ((char *)0) can be
+ used to force out output from the wrap_buffer. */
+
+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_per_line == UINT_MAX) /* No line overflow checking */
+ {
+ wrap_column = 0;
+ }
+ else if (chars_printed >= chars_per_line)
+ {
+ puts_filtered ("\n");
+ if (indent != NULL)
+ puts_filtered (indent);
+ wrap_column = 0;
+ }
+ else
+ {
+ wrap_column = chars_printed;
+ if (indent == NULL)
+ wrap_indent = "";
+ else
+ wrap_indent = indent;
+ }
+}
+
+/* Ensure that whatever gets printed next, using the filtered output
+ commands, starts at the beginning of the line. I.E. if there is
+ any pending output for the current line, flush it and start a new
+ line. Otherwise do nothing. */
+
+void
+begin_line ()
+{
+ if (chars_printed > 0)
+ {
+ puts_filtered ("\n");
+ }
+}
+
+/* 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)
+ const char *linebuffer;
+ FILE *stream;
+{
+ const 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)
+ {
+ 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 ((char *)0); /* Spit out chars, cancel further wraps */
+ lines_printed++;
+ putc ('\n', stream);
+ lineptr++;
+ }
+ }
+}
+
+/* Print a variable number of ARGS using format FORMAT. If this
+ information is going to put the amount written (since the last call
+ to REINITIALIZE_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. */
+
+#define MIN_LINEBUF 255
+
+void
+vfprintf_filtered (stream, format, args)
+ FILE *stream;
+ char *format;
+ va_list args;
+{
+ char line_buf[MIN_LINEBUF+10];
+ char *linebuffer = line_buf;
+ int format_length;
+
+ format_length = strlen (format);
+
+ /* Reallocate buffer to a larger size if this is necessary. */
+ if (format_length * 2 > MIN_LINEBUF)
+ {
+ linebuffer = alloca (10 + format_length * 2);
+ }
+
+ /* This won't blow up if the restrictions described above are
+ followed. */
+ vsprintf (linebuffer, format, args);
+
+ fputs_filtered (linebuffer, stream);
+}
+
+void
+vprintf_filtered (format, args)
+ char *format;
+ va_list args;
+{
+ vfprintf_filtered (stdout, format, args);
+}
+
+/* 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. */
+ vfprintf_filtered (stream, format, args);
+ va_end (args);
+}
+
+/* Like fprintf_filtered, but prints it's result indent.
+ Called as fprintfi_filtered (spaces, stream, format, ...); */
+
+/* VARARGS */
+void
+fprintfi_filtered (va_alist)
+ va_dcl
+{
+ va_list args;
+ int spaces;
+ FILE *stream;
+ char *format;
+
+ va_start (args);
+ spaces = va_arg (args, int);
+ stream = va_arg (args, FILE *);
+ format = va_arg (args, char *);
+ print_spaces_filtered (spaces, stream);
+
+ /* This won't blow up if the restrictions described above are
+ followed. */
+ 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 *);
+
+ vfprintf_filtered (stdout, format, args);
+ va_end (args);
+}
+
+/* Like printf_filtered, but prints it's result indented.
+ Called as printfi_filtered (spaces, format, ...); */
+
+/* VARARGS */
+void
+printfi_filtered (va_alist)
+ va_dcl
+{
+ va_list args;
+ int spaces;
+ char *format;
+
+ va_start (args);
+ spaces = va_arg (args, int);
+ format = va_arg (args, char *);
+ print_spaces_filtered (spaces, stdout);
+ vfprintf_filtered (stdout, format, args);
+ va_end (args);
+}
+
+/* Easy -- but watch out!
+
+ This routine is *not* a replacement for puts()! puts() appends a newline.
+ This one doesn't, and had better not! */
+
+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 = (char *) xmalloc (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);
+}
+
+/* C++ demangler stuff. */
+
+/* fprintf_symbol_filtered attempts to demangle NAME, a symbol in language
+ LANG, using demangling args ARG_MODE, and print it filtered to STREAM.
+ If the name is not mangled, or the language for the name is unknown, or
+ demangling is off, the name is printed in its "raw" form. */
+
+void
+fprintf_symbol_filtered (stream, name, lang, arg_mode)
+ FILE *stream;
+ char *name;
+ enum language lang;
+ int arg_mode;
+{
+ char *demangled;
+
+ if (name != NULL)
+ {
+ /* If user wants to see raw output, no problem. */
+ if (!demangle)
+ {
+ fputs_filtered (name, stream);
+ }
+ else
+ {
+ switch (lang)
+ {
+ case language_cplus:
+ demangled = cplus_demangle (name, arg_mode);
+ break;
+ case language_chill:
+ demangled = chill_demangle (name);
+ break;
+ default:
+ demangled = NULL;
+ break;
+ }
+ fputs_filtered (demangled ? demangled : name, stream);
+ if (demangled != NULL)
+ {
+ free (demangled);
+ }
+ }
+ }
+}
+
+/* Do a strcmp() type operation on STRING1 and STRING2, ignoring any
+ differences in whitespace. Returns 0 if they match, non-zero if they
+ don't (slightly different than strcmp()'s range of return values).
+
+ As an extra hack, string1=="FOO(ARGS)" matches string2=="FOO".
+ This "feature" is useful when searching for matching C++ function names
+ (such as if the user types 'break FOO', where FOO is a mangled C++
+ function). */
+
+int
+strcmp_iw (string1, string2)
+ const char *string1;
+ const char *string2;
+{
+ while ((*string1 != '\0') && (*string2 != '\0'))
+ {
+ while (isspace (*string1))
+ {
+ string1++;
+ }
+ while (isspace (*string2))
+ {
+ string2++;
+ }
+ if (*string1 != *string2)
+ {
+ break;
+ }
+ if (*string1 != '\0')
+ {
+ string1++;
+ string2++;
+ }
+ }
+ return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0');
+}
+
+
+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.sfunc = 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. */
+#if defined(__GO32__)
+ lines_per_page = ScreenRows();
+ chars_per_line = ScreenCols();
+#else
+ 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;
+ }
+ }
+ }
+
+#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
+
+ /* If there is a better way to determine the window size, use it. */
+ SIGWINCH_HANDLER ();
+#endif
+#endif
+ /* If the output is not a terminal, don't paginate it. */
+ if (!ISATTY (stdout))
+ lines_per_page = UINT_MAX;
+
+ 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.",
+ &setprintlist),
+ &showprintlist);
+
+ 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.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("asm-demangle", class_support, var_boolean,
+ (char *)&asm_demangle,
+ "Set demangling of C++ names in disassembly listings.",
+ &setprintlist),
+ &showprintlist);
+}
+
+/* Machine specific function to handle SIGWINCH signal. */
+
+#ifdef SIGWINCH_HANDLER_BODY
+ SIGWINCH_HANDLER_BODY
+#endif
+
diff --git a/gnu/usr.bin/gdb/gdb/valarith.c b/gnu/usr.bin/gdb/gdb/valarith.c
new file mode 100644
index 000000000000..3711a150d28c
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/valarith.c
@@ -0,0 +1,969 @@
+/* Perform arithmetic and other operations on values, for GDB.
+ Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "value.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "target.h"
+#include "language.h"
+#include <string.h>
+
+/* Define whether or not the C operator '/' truncates towards zero for
+ differently signed operands (truncation direction is undefined in C). */
+
+#ifndef TRUNCATION_TOWARDS_ZERO
+#define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2)
+#endif
+
+static value
+value_subscripted_rvalue PARAMS ((value, value));
+
+
+value
+value_add (arg1, arg2)
+ value arg1, arg2;
+{
+ register value 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 *) */
+ return value_from_longest (VALUE_TYPE (valptr),
+ value_as_long (valptr)
+ + (len * value_as_long (valint)));
+ }
+
+ return value_binop (arg1, arg2, BINOP_ADD);
+}
+
+value
+value_sub (arg1, arg2)
+ value arg1, arg2;
+{
+
+ 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. */
+ return value_from_longest
+ (VALUE_TYPE (arg1),
+ value_as_long (arg1)
+ - (TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)))
+ * value_as_long (arg2)));
+ }
+ else if (VALUE_TYPE (arg1) == VALUE_TYPE (arg2))
+ {
+ /* pointer to <type x> - pointer to <type x>. */
+ return value_from_longest
+ (builtin_type_long, /* FIXME -- should be ptrdiff_t */
+ (value_as_long (arg1) - value_as_long (arg2))
+ / TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))));
+ }
+ 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].
+ See comments in value_coerce_array() for rationale for reason for
+ doing lower bounds adjustment here rather than there.
+ FIXME: Perhaps we should validate that the index is valid and if
+ verbosity is set, warn about invalid indices (but still use them). */
+
+value
+value_subscript (array, idx)
+ value array, idx;
+{
+ int lowerbound;
+ value bound;
+ struct type *range_type;
+
+ COERCE_REF (array);
+
+ if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_ARRAY)
+ {
+ range_type = TYPE_FIELD_TYPE (VALUE_TYPE (array), 0);
+ lowerbound = TYPE_FIELD_BITPOS (range_type, 0);
+ if (lowerbound != 0)
+ {
+ bound = value_from_longest (builtin_type_int, (LONGEST) lowerbound);
+ idx = value_sub (idx, bound);
+ }
+ if (VALUE_LVAL (array) != lval_memory)
+ {
+ return value_subscripted_rvalue (array, idx);
+ }
+ }
+ 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. */
+
+static 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 * longest_to_int (value_as_long (idx));
+ value v;
+
+ if (elt_offs >= TYPE_LENGTH (VALUE_TYPE (array)))
+ error ("no such vector element");
+
+ v = allocate_value (elt_type);
+ memcpy (VALUE_CONTENTS (v), VALUE_CONTENTS (array) + elt_offs, 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;
+}
+
+/* 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++).
+
+ OP is the operatore, and if it is BINOP_ASSIGN_MODIFY, then OTHEROP
+ is the opcode saying how to modify it. Otherwise, OTHEROP is
+ unused. */
+
+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_REF (arg1);
+ COERCE_REF (arg2);
+ 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_BITWISE_AND: strcpy(ptr,"&"); break;
+ case BINOP_BITWISE_IOR: strcpy(ptr,"|"); break;
+ case BINOP_BITWISE_XOR: strcpy(ptr,"^"); break;
+ case BINOP_LOGICAL_AND: strcpy(ptr,"&&"); break;
+ case BINOP_LOGICAL_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_BITWISE_AND: strcpy(ptr,"&="); break;
+ case BINOP_BITWISE_IOR: strcpy(ptr,"|="); break;
+ case BINOP_BITWISE_XOR: strcpy(ptr,"^="); break;
+ case BINOP_MOD: /* invalid */
+ 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;
+ case BINOP_MOD: /* invalid */
+ 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 call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1);
+ }
+ error ("member function %s not found", tstr);
+#ifdef lint
+ return call_function_by_hand (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_LOGICAL_NOT: strcpy(ptr,"!"); break;
+ case UNOP_COMPLEMENT: 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 call_function_by_hand (argvec[0], 1 - static_memfuncp, argvec + 1);
+ }
+ error ("member function %s not found", tstr);
+ return 0; /* For lint -- never reached */
+}
+
+
+/* Concatenate two values with the following conditions:
+
+ (1) Both values must be either bitstring values or character string
+ values and the resulting value consists of the concatenation of
+ ARG1 followed by ARG2.
+
+ or
+
+ One value must be an integer value and the other value must be
+ either a bitstring value or character string value, which is
+ to be repeated by the number of times specified by the integer
+ value.
+
+
+ (2) Boolean values are also allowed and are treated as bit string
+ values of length 1.
+
+ (3) Character values are also allowed and are treated as character
+ string values of length 1.
+*/
+
+value
+value_concat (arg1, arg2)
+ value arg1, arg2;
+{
+ register value inval1, inval2, outval;
+ int inval1len, inval2len;
+ int count, idx;
+ char *ptr;
+ char inchar;
+
+ /* First figure out if we are dealing with two values to be concatenated
+ or a repeat count and a value to be repeated. INVAL1 is set to the
+ first of two concatenated values, or the repeat count. INVAL2 is set
+ to the second of the two concatenated values or the value to be
+ repeated. */
+
+ if (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)
+ {
+ inval1 = arg2;
+ inval2 = arg1;
+ }
+ else
+ {
+ inval1 = arg1;
+ inval2 = arg2;
+ }
+
+ /* Now process the input values. */
+
+ if (TYPE_CODE (VALUE_TYPE (inval1)) == TYPE_CODE_INT)
+ {
+ /* We have a repeat count. Validate the second value and then
+ construct a value repeated that many times. */
+ if (TYPE_CODE (VALUE_TYPE (inval2)) == TYPE_CODE_STRING
+ || TYPE_CODE (VALUE_TYPE (inval2)) == TYPE_CODE_CHAR)
+ {
+ count = longest_to_int (value_as_long (inval1));
+ inval2len = TYPE_LENGTH (VALUE_TYPE (inval2));
+ ptr = (char *) alloca (count * inval2len);
+ if (TYPE_CODE (VALUE_TYPE (inval2)) == TYPE_CODE_CHAR)
+ {
+ inchar = (char) unpack_long (VALUE_TYPE (inval2),
+ VALUE_CONTENTS (inval2));
+ for (idx = 0; idx < count; idx++)
+ {
+ *(ptr + idx) = inchar;
+ }
+ }
+ else
+ {
+ for (idx = 0; idx < count; idx++)
+ {
+ memcpy (ptr + (idx * inval2len), VALUE_CONTENTS (inval2),
+ inval2len);
+ }
+ }
+ outval = value_string (ptr, count * inval2len);
+ }
+ else if (TYPE_CODE (VALUE_TYPE (inval2)) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (VALUE_TYPE (inval2)) == TYPE_CODE_BOOL)
+ {
+ error ("unimplemented support for bitstring/boolean repeats");
+ }
+ else
+ {
+ error ("can't repeat values of that type");
+ }
+ }
+ else if (TYPE_CODE (VALUE_TYPE (inval1)) == TYPE_CODE_STRING
+ || TYPE_CODE (VALUE_TYPE (inval1)) == TYPE_CODE_CHAR)
+ {
+ /* We have two character strings to concatenate. */
+ if (TYPE_CODE (VALUE_TYPE (inval2)) != TYPE_CODE_STRING
+ && TYPE_CODE (VALUE_TYPE (inval2)) != TYPE_CODE_CHAR)
+ {
+ error ("Strings can only be concatenated with other strings.");
+ }
+ inval1len = TYPE_LENGTH (VALUE_TYPE (inval1));
+ inval2len = TYPE_LENGTH (VALUE_TYPE (inval2));
+ ptr = (char *) alloca (inval1len + inval2len);
+ if (TYPE_CODE (VALUE_TYPE (inval1)) == TYPE_CODE_CHAR)
+ {
+ *ptr = (char) unpack_long (VALUE_TYPE (inval1), VALUE_CONTENTS (inval1));
+ }
+ else
+ {
+ memcpy (ptr, VALUE_CONTENTS (inval1), inval1len);
+ }
+ if (TYPE_CODE (VALUE_TYPE (inval2)) == TYPE_CODE_CHAR)
+ {
+ *(ptr + inval1len) =
+ (char) unpack_long (VALUE_TYPE (inval2), VALUE_CONTENTS (inval2));
+ }
+ else
+ {
+ memcpy (ptr + inval1len, VALUE_CONTENTS (inval2), inval2len);
+ }
+ outval = value_string (ptr, inval1len + inval2len);
+ }
+ else if (TYPE_CODE (VALUE_TYPE (inval1)) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (VALUE_TYPE (inval1)) == TYPE_CODE_BOOL)
+ {
+ /* We have two bitstrings to concatenate. */
+ if (TYPE_CODE (VALUE_TYPE (inval2)) != TYPE_CODE_BITSTRING
+ && TYPE_CODE (VALUE_TYPE (inval2)) != TYPE_CODE_BOOL)
+ {
+ error ("Bitstrings or booleans can only be concatenated with other bitstrings or booleans.");
+ }
+ error ("unimplemented support for bitstring/boolean concatenation.");
+ }
+ else
+ {
+ /* We don't know how to concatenate these operands. */
+ error ("illegal operands for concatenation.");
+ }
+ return (outval);
+}
+
+
+/* Perform a binary operation on two operands which have reasonable
+ representations as integers or floats. This includes booleans,
+ characters, integers, or 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;
+ enum exp_opcode 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_CHAR
+ &&
+ TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_INT
+ &&
+ TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_BOOL)
+ ||
+ (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_FLT
+ &&
+ TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_CHAR
+ &&
+ TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT
+ &&
+ TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_BOOL))
+ error ("Argument to arithmetic operation not a number or boolean.");
+
+ 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 if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_BOOL
+ &&
+ TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_BOOL)
+ {
+ LONGEST v1, v2, v;
+ v1 = value_as_long (arg1);
+ v2 = value_as_long (arg2);
+
+ switch (op)
+ {
+ case BINOP_BITWISE_AND:
+ v = v1 & v2;
+ break;
+
+ case BINOP_BITWISE_IOR:
+ v = v1 | v2;
+ break;
+
+ case BINOP_BITWISE_XOR:
+ v = v1 ^ v2;
+ break;
+
+ default:
+ error ("Invalid operation on booleans.");
+ }
+
+ val = allocate_value (builtin_type_chill_bool);
+ store_signed_integer (VALUE_CONTENTS_RAW (val),
+ TYPE_LENGTH (VALUE_TYPE (val)),
+ v);
+ }
+ else
+ /* Integral operations here. */
+ /* FIXME: Also mixed integral/booleans, with result an integer. */
+ {
+ /* 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 (arg2)) >= 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_MOD:
+ /* Knuth 1.2.4, integer only. Note that unlike the C '%' op,
+ v1 mod 0 has a defined value, v1. */
+ /* Chill specifies that v2 must be > 0, so check for that. */
+ if (current_language -> la_language == language_chill
+ && value_as_long (arg2) <= 0)
+ {
+ error ("Second operand of MOD must be greater than zero.");
+ }
+ if (v2 == 0)
+ {
+ v = v1;
+ }
+ else
+ {
+ v = v1/v2;
+ /* Note floor(v1/v2) == v1/v2 for unsigned. */
+ v = v1 - (v2 * v);
+ }
+ break;
+
+ case BINOP_LSH:
+ v = v1 << v2;
+ break;
+
+ case BINOP_RSH:
+ v = v1 >> v2;
+ break;
+
+ case BINOP_BITWISE_AND:
+ v = v1 & v2;
+ break;
+
+ case BINOP_BITWISE_IOR:
+ v = v1 | v2;
+ break;
+
+ case BINOP_BITWISE_XOR:
+ v = v1 ^ v2;
+ break;
+
+ case BINOP_LOGICAL_AND:
+ v = v1 && v2;
+ break;
+
+ case BINOP_LOGICAL_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);
+ store_unsigned_integer (VALUE_CONTENTS_RAW (val),
+ TYPE_LENGTH (VALUE_TYPE (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_MOD:
+ /* Knuth 1.2.4, integer only. Note that unlike the C '%' op,
+ X mod 0 has a defined value, X. */
+ /* Chill specifies that v2 must be > 0, so check for that. */
+ if (current_language -> la_language == language_chill
+ && v2 <= 0)
+ {
+ error ("Second operand of MOD must be greater than zero.");
+ }
+ if (v2 == 0)
+ {
+ v = v1;
+ }
+ else
+ {
+ v = v1/v2;
+ /* Compute floor. */
+ if (TRUNCATION_TOWARDS_ZERO && (v < 0) && ((v1 % v2) != 0))
+ {
+ v--;
+ }
+ v = v1 - (v2 * v);
+ }
+ break;
+
+ case BINOP_LSH:
+ v = v1 << v2;
+ break;
+
+ case BINOP_RSH:
+ v = v1 >> v2;
+ break;
+
+ case BINOP_BITWISE_AND:
+ v = v1 & v2;
+ break;
+
+ case BINOP_BITWISE_IOR:
+ v = v1 | v2;
+ break;
+
+ case BINOP_BITWISE_XOR:
+ v = v1 ^ v2;
+ break;
+
+ case BINOP_LOGICAL_AND:
+ v = v1 && v2;
+ break;
+
+ case BINOP_LOGICAL_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);
+ store_signed_integer (VALUE_CONTENTS_RAW (val),
+ TYPE_LENGTH (VALUE_TYPE (val)),
+ v);
+ }
+ }
+
+ return val;
+}
+
+/* Simulate the C operator ! -- return 1 if ARG1 contains zero. */
+
+int
+value_logical_not (arg1)
+ value arg1;
+{
+ register int len;
+ register char *p;
+
+ COERCE_ARRAY (arg1);
+
+ if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_FLT)
+ return 0 == value_as_double (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);
+
+ /* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
+ is bigger. */
+ else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
+ return value_as_pointer (arg1) == (CORE_ADDR) value_as_long (arg2);
+ else if (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT)
+ return (CORE_ADDR) value_as_long (arg1) == value_as_pointer (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 LONGEST) value_as_long (arg1)
+ < (unsigned LONGEST) 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 && code2 == TYPE_CODE_PTR)
+ return value_as_pointer (arg1) < value_as_pointer (arg2);
+
+ /* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
+ is bigger. */
+ else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
+ return value_as_pointer (arg1) < (CORE_ADDR) value_as_long (arg2);
+ else if (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT)
+ return (CORE_ADDR) value_as_long (arg1) < value_as_pointer (arg2);
+
+ else
+ {
+ error ("Invalid type combination in ordering comparison.");
+ return 0;
+ }
+}
+
+/* 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_longest (type, - value_as_long (arg1));
+ else {
+ error ("Argument to negate operation not a number.");
+ return 0; /* For lint -- never reached */
+ }
+}
+
+value
+value_complement (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_longest (VALUE_TYPE (arg1), ~ value_as_long (arg1));
+}
+
diff --git a/gnu/usr.bin/gdb/gdb/valops.c b/gnu/usr.bin/gdb/gdb/valops.c
new file mode 100644
index 000000000000..dc4d82a8651c
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/valops.c
@@ -0,0 +1,1819 @@
+/* Perform non-arithmetic operations on values, for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "demangle.h"
+#include "language.h"
+
+#include <errno.h>
+
+/* Local functions. */
+
+static int
+typecmp PARAMS ((int staticp, struct type *t1[], value t2[]));
+
+static CORE_ADDR
+find_function_addr PARAMS ((value, struct type **));
+
+static CORE_ADDR
+value_push PARAMS ((CORE_ADDR, value));
+
+static CORE_ADDR
+value_arg_push PARAMS ((CORE_ADDR, value));
+
+static value
+search_struct_field PARAMS ((char *, value, int, struct type *, int));
+
+static value
+search_struct_method PARAMS ((char *, value *, value *, int, int *,
+ struct type *));
+
+static int
+check_field_in PARAMS ((struct type *, const char *));
+
+static CORE_ADDR
+allocate_space_in_inferior PARAMS ((int));
+
+
+/* Allocate NBYTES of space in the inferior using the inferior's malloc
+ and return a value that is a pointer to the allocated space. */
+
+static CORE_ADDR
+allocate_space_in_inferior (len)
+ int len;
+{
+ register value val;
+ register struct symbol *sym;
+ struct minimal_symbol *msymbol;
+ struct type *type;
+ value blocklen;
+ LONGEST maddr;
+
+ /* Find the address of malloc in the inferior. */
+
+ sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE, 0, NULL);
+ if (sym != NULL)
+ {
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ {
+ error ("\"malloc\" exists in this program but is not a function.");
+ }
+ val = value_of_variable (sym, NULL);
+ }
+ else
+ {
+ msymbol = lookup_minimal_symbol ("malloc", (struct objfile *) NULL);
+ if (msymbol != NULL)
+ {
+ type = lookup_pointer_type (builtin_type_char);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol);
+ val = value_from_longest (type, maddr);
+ }
+ else
+ {
+ error ("evaluation of this expression requires the program to have a function \"malloc\".");
+ }
+ }
+
+ blocklen = value_from_longest (builtin_type_int, (LONGEST) len);
+ val = call_function_by_hand (val, 1, &blocklen);
+ if (value_logical_not (val))
+ {
+ error ("No memory available to program.");
+ }
+ return (value_as_long (val));
+}
+
+/* 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 or object 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_STRUCT
+ && code2 == TYPE_CODE_STRUCT
+ && TYPE_NAME (type) != 0)
+ {
+ /* 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 object in addition to changing its type. */
+ value v = search_struct_field (type_name_no_tag (type),
+ arg2, 0, VALUE_TYPE (arg2), 1);
+ if (v)
+ {
+ VALUE_TYPE (v) = type;
+ return v;
+ }
+ }
+ 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_longest (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, 1);
+ 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 if (code1 == TYPE_CODE_VOID)
+ {
+ return value_zero (builtin_type_void, not_lval);
+ }
+ 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);
+
+ memset (VALUE_CONTENTS (val), 0, 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.
+
+ If the value is zero-length, we avoid calling read_memory, which would
+ abort. We mark the value as fetched anyway -- all 0 bytes of it.
+
+ 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);
+
+ if (TYPE_LENGTH (VALUE_TYPE (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);
+ COERCE_REF (toval);
+
+ 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);
+ memcpy (virtual_buffer, VALUE_CONTENTS (fromval),
+ REGISTER_VIRTUAL_SIZE (regno));
+ REGISTER_CONVERT_TO_RAW (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),
+ (char *) &v, sizeof v);
+ modify_field ((char *) &v, 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),
+ (char *) &v, sizeof v);
+ modify_field ((char *) &v, value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ (char *) &v, sizeof v);
+ }
+ else if (use_buffer)
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ raw_buffer, use_buffer);
+ else
+ {
+ /* Do any conversion necessary when storing this type to more
+ than one register. */
+#ifdef REGISTER_CONVERT_FROM_TYPE
+ memcpy (raw_buffer, VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+ REGISTER_CONVERT_FROM_TYPE(VALUE_REGNO (toval), type, raw_buffer);
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ raw_buffer, TYPE_LENGTH (type));
+#else
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+#endif
+ }
+ 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,
+ value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ else if (use_buffer)
+ memcpy (buffer + byte_offset, raw_buffer, use_buffer);
+ else
+ memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval),
+ 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);
+ }
+
+ /* FIXME: This loses if fromval is a different size than toval, for
+ example because fromval got cast in the REGISTER_CONVERTIBLE case
+ above. */
+ val = allocate_value (type);
+ memcpy (val, toval, VALUE_CONTENTS_RAW (val) - (char *) val);
+ memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval),
+ 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, b)
+ struct symbol *var;
+ struct block *b;
+{
+ value val;
+ FRAME fr;
+
+ if (b == NULL)
+ /* Use selected frame. */
+ fr = NULL;
+ else
+ {
+ fr = block_innermost_frame (b);
+ if (fr == NULL && symbol_read_needs_frame (var))
+ {
+ if (BLOCK_FUNCTION (b) != NULL
+ && SYMBOL_NAME (BLOCK_FUNCTION (b)) != NULL)
+ error ("No frame is currently executing in block %s.",
+ SYMBOL_NAME (BLOCK_FUNCTION (b)));
+ else
+ error ("No frame is currently executing in specified block");
+ }
+ }
+ val = read_var_value (var, fr);
+ if (val == 0)
+ error ("Address of symbol \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var));
+ return val;
+}
+
+/* Given a value which is an array, return a value which is a pointer to its
+ first element, regardless of whether or not the array has a nonzero lower
+ bound.
+
+ FIXME: A previous comment here indicated that this routine should be
+ substracting the array's lower bound. It's not clear to me that this
+ is correct. Given an array subscripting operation, it would certainly
+ work to do the adjustment here, essentially computing:
+
+ (&array[0] - (lowerbound * sizeof array[0])) + (index * sizeof array[0])
+
+ However I believe a more appropriate and logical place to account for
+ the lower bound is to do so in value_subscript, essentially computing:
+
+ (&array[0] + ((index - lowerbound) * sizeof array[0]))
+
+ As further evidence consider what would happen with operations other
+ than array subscripting, where the caller would get back a value that
+ had an address somewhere before the actual first element of the array,
+ and the information about the lower bound would be lost because of
+ the coercion to pointer type.
+ */
+
+value
+value_coerce_array (arg1)
+ value arg1;
+{
+ register struct type *type;
+
+ 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);
+
+ return value_from_longest (lookup_pointer_type (type),
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+}
+
+/* Given a value which is a function, return a value which is a pointer
+ to it. */
+
+value
+value_coerce_function (arg1)
+ value arg1;
+{
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Attempt to take address of value not located in memory.");
+
+ return value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)),
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+}
+
+/* Return a pointer value for the object for which ARG1 is the contents. */
+
+value
+value_addr (arg1)
+ value arg1;
+{
+ struct type *type = VALUE_TYPE (arg1);
+ if (TYPE_CODE (type) == TYPE_CODE_REF)
+ {
+ /* Copy the value, but change the type from (T&) to (T*).
+ We keep the same location information, which is efficient,
+ and allows &(&X) to get the location containing the reference. */
+ value arg2 = value_copy (arg1);
+ VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type));
+ return arg2;
+ }
+ if (VALUE_REPEATED (arg1)
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ return value_coerce_array (arg1);
+ if (TYPE_CODE (type) == 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.");
+
+ return value_from_longest (lookup_pointer_type (type),
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+}
+
+/* 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)),
+ value_as_pointer (arg1));
+ error ("Attempt to take contents of a non-pointer value.");
+ return 0; /* For lint -- never reached */
+}
+
+/* Pushing small parts of stack frames. */
+
+/* Push one word (the size of object that a register holds). */
+
+CORE_ADDR
+push_word (sp, word)
+ CORE_ADDR sp;
+ REGISTER_TYPE word;
+{
+ register int len = sizeof (REGISTER_TYPE);
+ char buffer[MAX_REGISTER_RAW_SIZE];
+
+ store_unsigned_integer (buffer, len, word);
+#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 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. */
+
+static 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;
+
+ /* FIXME: We should coerce this according to the prototype (if we have
+ one). Right now we do a little bit of this in typecmp(), but that
+ doesn't always get called. For example, if passing a ref to a function
+ without a prototype, we probably should de-reference it. Currently
+ we don't. */
+
+ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM)
+ arg = value_cast (builtin_type_unsigned_int, arg);
+
+#if 1 /* FIXME: This is only a temporary patch. -fnf */
+ 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);
+#endif
+
+ type = VALUE_TYPE (arg);
+
+ if (TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
+ return value_cast (builtin_type_int, arg);
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
+ return value_cast (builtin_type_double, arg);
+
+ return arg;
+}
+
+/* Push the value ARG, first coercing it as an argument
+ to a C function. */
+
+static 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. */
+
+static 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_pointer (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_pointer (value_addr (function));
+ else
+ /* Handle integer used as address of a function. */
+ funaddr = (CORE_ADDR) 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;
+ /* CALL_DUMMY is an array of words (REGISTER_TYPE), but each word
+ is in host byte order. It is switched to target byte order before calling
+ FIX_CALL_DUMMY. */
+ 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;
+ CORE_ADDR real_pc;
+
+ if (!target_has_execution)
+ noprocess();
+
+ 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_sp ();
+
+#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. */
+ for (i = 0; i < sizeof dummy / sizeof (REGISTER_TYPE); i++)
+ store_unsigned_integer (&dummy1[i], sizeof (REGISTER_TYPE),
+ (unsigned LONGEST)dummy[i]);
+
+#ifdef GDB_TARGET_IS_HPPA
+ real_pc = FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+ value_type, using_gcc);
+#else
+ FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+ value_type, using_gcc);
+ real_pc = start_sp;
+#endif
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+ write_memory (start_sp, (char *)dummy1, sizeof dummy);
+#endif /* 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. */
+ {
+ extern CORE_ADDR text_end;
+ 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;
+ real_pc = text_end - sizeof dummy;
+ write_memory (real_pc, (char *)dummy1, sizeof dummy);
+ }
+#endif /* Before text_end. */
+
+#if CALL_DUMMY_LOCATION == AFTER_TEXT_END
+ {
+ extern CORE_ADDR text_end;
+ int errcode;
+ sp = old_sp;
+ real_pc = text_end;
+ errcode = target_write_memory (real_pc, (char *)dummy1, sizeof dummy);
+ if (errcode != 0)
+ error ("Cannot write text segment -- call_function failed");
+ }
+#endif /* After text_end. */
+
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+ real_pc = funaddr;
+#endif /* At entry point. */
+
+#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_longest (lookup_pointer_type (value_type),
+ (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 store_inferior_registers in sparc-nat.c.) */
+ write_sp (sp);
+
+ {
+ char retbuf[REGISTER_BYTES];
+ char *name;
+ struct symbol *symbol;
+
+ name = NULL;
+ symbol = find_pc_function (funaddr);
+ if (symbol)
+ {
+ name = SYMBOL_SOURCE_NAME (symbol);
+ }
+ else
+ {
+ /* Try the minimal symbols. */
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
+
+ if (msymbol)
+ {
+ name = SYMBOL_SOURCE_NAME (msymbol);
+ }
+ }
+ if (name == NULL)
+ {
+ char format[80];
+ sprintf (format, "at %s", local_hex_format ());
+ name = alloca (80);
+ sprintf (name, format, (unsigned long) funaddr);
+ }
+
+ /* Execute the stack dummy routine, calling FUNCTION.
+ When it is done, discard the empty frame
+ after storing the contents of all regs into retbuf. */
+ if (run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf))
+ {
+ /* We stopped somewhere besides the call dummy. */
+
+ /* If we did the cleanups, we would print a spurious error message
+ (Unable to restore previously selected frame), would write the
+ registers from the inf_status (which is wrong), and would do other
+ wrong things (like set stop_bpstat to the wrong thing). */
+ discard_cleanups (old_chain);
+ /* Prevent memory leak. */
+ bpstat_clear (&inf_status.stop_bpstat);
+
+ /* The following error message used to say "The expression
+ which contained the function call has been discarded." It
+ is a hard concept to explain in a few words. Ideally, GDB
+ would be able to resume evaluation of the expression when
+ the function finally is done executing. Perhaps someday
+ this will be implemented (it would not be easy). */
+
+ /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
+ a C++ name with arguments and stuff. */
+ error ("\
+The program being debugged stopped while in a function called from GDB.\n\
+When the function (%s) is done executing, GDB will silently\n\
+stop (instead of continuing to evaluate the expression containing\n\
+the function call).", name);
+ }
+
+ do_cleanups (old_chain);
+
+ /* Figure out the value returned by the function. */
+ 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. */
+
+
+/* Create a value for an array by allocating space in the inferior, copying
+ the data into that space, and then setting up an array value.
+
+ The array bounds are set from LOWBOUND and HIGHBOUND, and the array is
+ populated from the values passed in ELEMVEC.
+
+ The element type of the array is inherited from the type of the
+ first element, and all elements must have the same size (though we
+ don't currently enforce any restriction on their types). */
+
+value
+value_array (lowbound, highbound, elemvec)
+ int lowbound;
+ int highbound;
+ value *elemvec;
+{
+ int nelem;
+ int idx;
+ int typelength;
+ value val;
+ struct type *rangetype;
+ struct type *arraytype;
+ CORE_ADDR addr;
+
+ /* Validate that the bounds are reasonable and that each of the elements
+ have the same size. */
+
+ nelem = highbound - lowbound + 1;
+ if (nelem <= 0)
+ {
+ error ("bad array bounds (%d, %d)", lowbound, highbound);
+ }
+ typelength = TYPE_LENGTH (VALUE_TYPE (elemvec[0]));
+ for (idx = 0; idx < nelem; idx++)
+ {
+ if (TYPE_LENGTH (VALUE_TYPE (elemvec[idx])) != typelength)
+ {
+ error ("array elements must all be the same size");
+ }
+ }
+
+ /* Allocate space to store the array in the inferior, and then initialize
+ it by copying in each element. FIXME: Is it worth it to create a
+ local buffer in which to collect each value and then write all the
+ bytes in one operation? */
+
+ addr = allocate_space_in_inferior (nelem * typelength);
+ for (idx = 0; idx < nelem; idx++)
+ {
+ write_memory (addr + (idx * typelength), VALUE_CONTENTS (elemvec[idx]),
+ typelength);
+ }
+
+ /* Create the array type and set up an array value to be evaluated lazily. */
+
+ rangetype = create_range_type ((struct type *) NULL, builtin_type_int,
+ lowbound, highbound);
+ arraytype = create_array_type ((struct type *) NULL,
+ VALUE_TYPE (elemvec[0]), rangetype);
+ val = value_at_lazy (arraytype, addr);
+ return (val);
+}
+
+/* Create a value for a string constant by allocating space in the inferior,
+ copying the data into that space, and returning the address with type
+ TYPE_CODE_STRING. PTR points to the string constant data; LEN is number
+ of characters.
+ Note that string types are like array of char types with a lower bound of
+ zero and an upper bound of LEN - 1. Also note that the string may contain
+ embedded null bytes. */
+
+value
+value_string (ptr, len)
+ char *ptr;
+ int len;
+{
+ value val;
+ struct type *rangetype;
+ struct type *stringtype;
+ CORE_ADDR addr;
+
+ /* Allocate space to store the string in the inferior, and then
+ copy LEN bytes from PTR in gdb to that address in the inferior. */
+
+ addr = allocate_space_in_inferior (len);
+ write_memory (addr, ptr, len);
+
+ /* Create the string type and set up a string value to be evaluated
+ lazily. */
+
+ rangetype = create_range_type ((struct type *) NULL, builtin_type_int,
+ 0, len - 1);
+ stringtype = create_string_type ((struct type *) NULL, rangetype);
+ val = value_at_lazy (stringtype, addr);
+ return (val);
+}
+
+/* See if we can pass arguments in T2 to a function which takes arguments
+ of types T1. Both t1 and t2 are NULL-terminated vectors. If some
+ arguments need coercion of some sort, then the coerced values are written
+ into T2. Return value is 0 if the arguments could be matched, or the
+ position at which they differ if not.
+
+ 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. */
+
+static int
+typecmp (staticp, t1, t2)
+ int staticp;
+ struct type *t1[];
+ value t2[];
+{
+ int i;
+
+ if (t2 == 0)
+ return 1;
+ if (staticp && t1 == 0)
+ return t2[1] != 0;
+ if (t1 == 0)
+ return 1;
+ if (TYPE_CODE (t1[0]) == TYPE_CODE_VOID) return 0;
+ if (t1[!staticp] == 0) return 0;
+ for (i = !staticp; t1[i] && TYPE_CODE (t1[i]) != TYPE_CODE_VOID; i++)
+ {
+ if (! t2[i])
+ return i+1;
+ if (TYPE_CODE (t1[i]) == TYPE_CODE_REF
+ /* We should be doing hairy argument matching, as below. */
+ && (TYPE_CODE (TYPE_TARGET_TYPE (t1[i]))
+ == TYPE_CODE (VALUE_TYPE (t2[i]))))
+ {
+ t2[i] = value_addr (t2[i]);
+ continue;
+ }
+
+ if (TYPE_CODE (t1[i]) == TYPE_CODE_PTR
+ && TYPE_CODE (VALUE_TYPE (t2[i])) == TYPE_CODE_ARRAY)
+ /* Array to pointer is a `trivial conversion' according to the ARM. */
+ continue;
+
+ /* We should be doing much hairier argument matching (see section 13.2
+ of the ARM), but as a quick kludge, just check for the same type
+ code. */
+ if (TYPE_CODE (t1[i]) != TYPE_CODE (VALUE_TYPE (t2[i])))
+ return i+1;
+ }
+ if (!t1[i]) return 0;
+ return t2[i] ? i+1 : 0;
+}
+
+/* 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 search in it assuming it has (class) type TYPE.
+ If found, return value, else return NULL.
+
+ If LOOKING_FOR_BASECLASS, then instead of looking for struct fields,
+ look for a baseclass named NAME. */
+
+static value
+search_struct_field (name, arg1, offset, type, looking_for_baseclass)
+ char *name;
+ register value arg1;
+ int offset;
+ register struct type *type;
+ int looking_for_baseclass;
+{
+ int i;
+
+ check_stub_type (type);
+
+ if (! looking_for_baseclass)
+ 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 && STREQ (t_field_name, name))
+ {
+ value v;
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, i);
+ struct symbol *sym =
+ lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym == NULL)
+ error ("Internal error: could not find physical static variable named %s",
+ phys_name);
+ v = value_at (TYPE_FIELD_TYPE (type, i),
+ (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+ }
+ else
+ v = value_primitive_field (arg1, offset, i, type);
+ if (v == 0)
+ error("there is no field named %s", name);
+ return v;
+ }
+ }
+
+ 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. But it could happen that the base part's member name
+ is not yet filled in. */
+ int found_baseclass = (looking_for_baseclass
+ && TYPE_BASECLASS_NAME (type, i) != NULL
+ && STREQ (name, TYPE_BASECLASS_NAME (type, i)));
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ value v2;
+ /* Fix to use baseclass_offset instead. FIXME */
+ baseclass_addr (type, i, VALUE_CONTENTS (arg1) + offset,
+ &v2, (int *)NULL);
+ if (v2 == 0)
+ error ("virtual baseclass botch");
+ if (found_baseclass)
+ return v2;
+ v = search_struct_field (name, v2, 0, TYPE_BASECLASS (type, i),
+ looking_for_baseclass);
+ }
+ else 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),
+ looking_for_baseclass);
+ 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 search in it assuming it has (class) type TYPE.
+ If found, return value, else if name matched and args not return (value)-1,
+ else return NULL. */
+
+static value
+search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
+ char *name;
+ register value *arg1p, *args;
+ int offset, *static_memfuncp;
+ register struct type *type;
+{
+ int i;
+ static int name_matched = 0;
+
+ 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 && STREQ (t_field_name, name))
+ {
+ int j = TYPE_FN_FIELDLIST_LENGTH (type, i) - 1;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ name_matched = 1;
+
+ if (j > 0 && args == 0)
+ error ("cannot resolve overloaded method `%s'", name);
+ while (j >= 0)
+ {
+ if (TYPE_FN_FIELD_STUB (f, j))
+ 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 (arg1p, f, j, type, offset);
+ if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
+ *static_memfuncp = 1;
+ return (value)value_fn_field (arg1p, f, j, type, offset);
+ }
+ j--;
+ }
+ }
+ }
+
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ value v;
+ int base_offset;
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ base_offset = baseclass_offset (type, i, *arg1p, offset);
+ if (base_offset == -1)
+ error ("virtual baseclass botch");
+ }
+ else
+ {
+ base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;
+ }
+ v = search_struct_method (name, arg1p, args, base_offset + offset,
+ static_memfuncp, TYPE_BASECLASS (type, i));
+ if (v == (value) -1)
+ {
+ name_matched = 1;
+ }
+ else if (v)
+ {
+/* FIXME-bothner: Why is this commented out? Why is it here? */
+/* *arg1p = arg1_tmp;*/
+ return v;
+ }
+ }
+ if (name_matched) return (value) -1;
+ else 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;
+ 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)
+ {
+ *argp = value_ind (*argp);
+ /* Don't coerce fn pointer to fn and then back again! */
+ if (TYPE_CODE (VALUE_TYPE (*argp)) != TYPE_CODE_FUNC)
+ 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 field first, because if we succeed, there
+ is less work to be done. */
+ v = search_struct_field (name, *argp, 0, t, 0);
+ 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 (NULL, TYPE_FN_FIELDLIST1 (t, 0),
+ TYPE_FN_FIELDLIST_LENGTH (t, 0),
+ 0, 0);
+ }
+ else
+ {
+ error ("destructor should not have any argument");
+ }
+ }
+ else
+ v = search_struct_method (name, argp, args, 0, static_memfuncp, t);
+
+ if (v == (value) -1)
+ {
+ error("Argument list of %s mismatch with component in the structure.", name);
+ }
+ else 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, 0);
+ }
+
+ 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)
+ const char *name;
+ const struct type *type;
+{
+ /* destructors are a special case. */
+
+ if (name[0] == '~')
+ {
+ char *dname = type_name_no_tag (type);
+ if (!STREQ (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;
+ const 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 && STREQ (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 (STREQ (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;
+ const 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 CURTYPE, 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". This function is used
+ to resolve user expressions of the form "DOMAIN::NAME". */
+
+value
+value_struct_elt_for_reference (domain, offset, curtype, name, intype)
+ struct type *domain, *curtype, *intype;
+ int offset;
+ char *name;
+{
+ register struct type *t = curtype;
+ register int i;
+ value v;
+
+ if ( TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error ("Internal error: non-aggregate type to value_struct_elt_for_reference");
+
+ 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 && STREQ (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 == NULL)
+ error ("Internal error: could not find physical static variable named %s",
+ phys_name);
+ return value_at (SYMBOL_TYPE (sym),
+ (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+ }
+ if (TYPE_FIELD_PACKED (t, i))
+ error ("pointers to bitfield members not allowed");
+
+ return value_from_longest
+ (lookup_reference_type (lookup_member_type (TYPE_FIELD_TYPE (t, i),
+ domain)),
+ offset + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
+ }
+ }
+
+ /* 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, t))
+ {
+ error ("member pointers to destructors not implemented yet");
+ }
+
+ /* Perform all necessary dereferencing. */
+ while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR)
+ intype = TYPE_TARGET_TYPE (intype);
+
+ for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
+ {
+ if (STREQ (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_STUB (f, j))
+ check_stub_method (t, i, j);
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ {
+ return value_from_longest
+ (lookup_reference_type
+ (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
+ domain)),
+ (LONGEST) METHOD_PTR_FROM_VOFFSET
+ (TYPE_FN_FIELD_VOFFSET (f, j)));
+ }
+ else
+ {
+ struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
+ 0, VAR_NAMESPACE, 0, NULL);
+ if (s == NULL)
+ {
+ v = 0;
+ }
+ else
+ {
+ v = read_var_value (s, 0);
+#if 0
+ VALUE_TYPE (v) = lookup_reference_type
+ (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
+ domain));
+#endif
+ }
+ return v;
+ }
+ }
+ }
+ for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--)
+ {
+ value v;
+ int base_offset;
+
+ if (BASETYPE_VIA_VIRTUAL (t, i))
+ base_offset = 0;
+ else
+ base_offset = TYPE_BASECLASS_BITPOS (t, i) / 8;
+ v = value_struct_elt_for_reference (domain,
+ offset + base_offset,
+ TYPE_BASECLASS (t, i),
+ name,
+ intype);
+ if (v)
+ return v;
+ }
+ return 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/gnu/usr.bin/gdb/gdb/valprint.c b/gnu/usr.bin/gdb/gdb/valprint.c
new file mode 100644
index 000000000000..b805645a4ce2
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/valprint.c
@@ -0,0 +1,1063 @@
+/* Print values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <string.h>
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "obstack.h"
+#include "language.h"
+#include "demangle.h"
+
+#include <errno.h>
+
+/* Prototypes for local functions */
+
+static void
+print_hex_chars PARAMS ((FILE *, unsigned char *, unsigned int));
+
+static void
+show_print PARAMS ((char *, int));
+
+static void
+set_print PARAMS ((char *, int));
+
+static void
+set_radix PARAMS ((char *, int));
+
+static void
+show_radix PARAMS ((char *, int));
+
+static void
+set_input_radix PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+set_input_radix_1 PARAMS ((int, unsigned));
+
+static void
+set_output_radix PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+set_output_radix_1 PARAMS ((int, unsigned));
+
+static void
+value_print_array_elements PARAMS ((value, FILE *, int, enum val_prettyprint));
+
+/* Maximum number of chars to print for a string pointer value or vector
+ contents, or UINT_MAX for no limit. Note that "set print elements 0"
+ stores UINT_MAX in print_max, which displays in a show command as
+ "unlimited". */
+
+unsigned int print_max;
+#define PRINT_MAX_DEFAULT 200 /* Start print_max off at this value. */
+
+/* Default input and output radixes, and output format letter. */
+
+unsigned input_radix = 10;
+unsigned output_radix = 10;
+int output_format = 0;
+
+/* Print repeat counts if there are more than this many repetitions of an
+ element in an array. Referenced by the low level language dependent
+ print routines. */
+
+unsigned int repeat_count_threshold = 10;
+
+int prettyprint_structs; /* Controls pretty printing of structures */
+int prettyprint_arrays; /* Controls pretty printing of arrays. */
+
+/* If nonzero, causes unions inside structures or other unions to be
+ printed. */
+
+int unionprint; /* Controls printing of nested unions. */
+
+/* If nonzero, causes machine addresses to be printed in certain contexts. */
+
+int addressprint; /* Controls printing of machine addresses */
+
+
+/* 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 using TYPE).
+
+ If DEREF_REF is nonzero, then dereference references, otherwise just print
+ them like pointers.
+
+ The PRETTY parameter controls prettyprinting.
+
+ If the data are a string pointer, returns the number of string characters
+ printed.
+
+ FIXME: The data at VALADDR is in target byte order. If gdb is ever
+ enhanced to be able to debug more than the single target it was compiled
+ for (specific CPU type and thus specific target byte ordering), then
+ either the print routines are going to have to take this into account,
+ or the data is going to have to be passed into here already converted
+ to the host byte ordering, whichever is more convenient. */
+
+
+int
+val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ if (pretty == Val_pretty_default)
+ {
+ pretty = prettyprint_structs ? Val_prettyprint : Val_no_prettyprint;
+ }
+
+ QUIT;
+
+ /* Ensure that the type is complete and not just a stub. If the type is
+ only a stub and we can't find and substitute its complete type, then
+ print appropriate string and return. Typical types that my be stubs
+ are structs, unions, and C++ methods. */
+
+ check_stub_type (type);
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ {
+ fprintf_filtered (stream, "<incomplete type>");
+ fflush (stream);
+ return (0);
+ }
+
+ return (LA_VAL_PRINT (type, valaddr, address, stream, format, deref_ref,
+ recurse, pretty));
+}
+
+/* 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;
+ int format;
+ enum val_prettyprint pretty;
+{
+ register unsigned int 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. */
+
+ 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)
+ LA_PRINT_STRING (stream, VALUE_CONTENTS (val), n, 0);
+ else
+ {
+ value_print_array_elements (val, stream, format, pretty);
+ }
+ fprintf_filtered (stream, "}");
+ return (n * typelen);
+ }
+ else
+ {
+ struct type *type = VALUE_TYPE (val);
+
+ /* 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 (type) == TYPE_CODE_PTR ||
+ TYPE_CODE (type) == TYPE_CODE_REF)
+ {
+ /* Hack: remove (char *) for char strings. Their
+ type is indicated by the quoted string anyway. */
+ if (TYPE_CODE (type) == TYPE_CODE_PTR &&
+ TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof(char) &&
+ TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT &&
+ !TYPE_UNSIGNED (TYPE_TARGET_TYPE (type)))
+ {
+ /* Print nothing */
+ }
+ else
+ {
+ fprintf_filtered (stream, "(");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, ") ");
+ }
+ }
+ return (val_print (type, VALUE_CONTENTS (val),
+ VALUE_ADDRESS (val), stream, format, 1, 0, pretty));
+ }
+}
+
+/* Called by various <lang>_val_print routines to print TYPE_CODE_INT's */
+
+void
+val_print_type_code_int (type, valaddr, stream)
+ struct type *type;
+ char *valaddr;
+ FILE *stream;
+{
+ char *p;
+ /* Pointer to first (i.e. lowest address) nonzero character. */
+ char *first_addr;
+ unsigned int len;
+
+ 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. */
+ 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) - 1;
+ 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. */
+ print_longest (stream, 'u', 0,
+ 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));
+ }
+ }
+ else
+ {
+#ifdef PRINT_TYPELESS_INTEGER
+ PRINT_TYPELESS_INTEGER (stream, type, unpack_long (type, valaddr));
+#else
+ print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0,
+ unpack_long (type, valaddr));
+#endif
+ }
+}
+
+/* Print a number according to FORMAT which is one of d,u,x,o,b,h,w,g.
+ The raison d'etre of this function is to consolidate printing of LONG_LONG's
+ into this one function. Some platforms have long longs but don't have a
+ printf() that supports "ll" in the format string. We handle these by seeing
+ if the number is actually a long, and if not we just bail out and print the
+ number in hex. The format chars b,h,w,g are from
+ print_scalar_formatted(). USE_LOCAL says whether or not to call the
+ local formatting routine to get the format. */
+
+void
+print_longest (stream, format, use_local, val_long)
+ FILE *stream;
+ int format;
+ int use_local;
+ LONGEST val_long;
+{
+#if defined (CC_HAS_LONG_LONG) && !defined (PRINTF_HAS_LONG_LONG)
+ long vtop, vbot;
+
+ vtop = val_long >> (sizeof (long) * HOST_CHAR_BIT);
+ vbot = (long) val_long;
+
+ if ((format == 'd' && (val_long < INT_MIN || val_long > INT_MAX))
+ || ((format == 'u' || format == 'x') && val_long > UINT_MAX))
+ {
+ fprintf_filtered (stream, "0x%lx%08lx", vtop, vbot);
+ return;
+ }
+#endif
+
+#ifdef PRINTF_HAS_LONG_LONG
+ switch (format)
+ {
+ case 'd':
+ fprintf_filtered (stream,
+ use_local ? local_decimal_format_custom ("ll")
+ : "%lld",
+ val_long);
+ break;
+ case 'u':
+ fprintf_filtered (stream, "%llu", val_long);
+ break;
+ case 'x':
+ fprintf_filtered (stream,
+ use_local ? local_hex_format_custom ("ll")
+ : "%llx",
+ val_long);
+ break;
+ case 'o':
+ fprintf_filtered (stream,
+ use_local ? local_octal_format_custom ("ll")
+ : "%llo",
+ break;
+ case 'b':
+ fprintf_filtered (stream, local_hex_format_custom ("02ll"), val_long);
+ break;
+ case 'h':
+ fprintf_filtered (stream, local_hex_format_custom ("04ll"), val_long);
+ break;
+ case 'w':
+ fprintf_filtered (stream, local_hex_format_custom ("08ll"), val_long);
+ break;
+ case 'g':
+ fprintf_filtered (stream, local_hex_format_custom ("016ll"), val_long);
+ break;
+ default:
+ abort ();
+ }
+#else /* !PRINTF_HAS_LONG_LONG */
+ /* In the following it is important to coerce (val_long) to a long. It does
+ nothing if !LONG_LONG, but it will chop off the top half (which we know
+ we can ignore) if the host supports long longs. */
+
+ switch (format)
+ {
+ case 'd':
+ fprintf_filtered (stream,
+ use_local ? local_decimal_format_custom ("l")
+ : "%ld",
+ (long) val_long);
+ break;
+ case 'u':
+ fprintf_filtered (stream, "%lu", (unsigned long) val_long);
+ break;
+ case 'x':
+ fprintf_filtered (stream,
+ use_local ? local_hex_format_custom ("l")
+ : "%lx",
+ (long) val_long);
+ break;
+ case 'o':
+ fprintf_filtered (stream,
+ use_local ? local_octal_format_custom ("l")
+ : "%lo",
+ (long) val_long);
+ break;
+ case 'b':
+ fprintf_filtered (stream, local_hex_format_custom ("02l"),
+ (long) val_long);
+ break;
+ case 'h':
+ fprintf_filtered (stream, local_hex_format_custom ("04l"),
+ (long) val_long);
+ break;
+ case 'w':
+ fprintf_filtered (stream, local_hex_format_custom ("08l"),
+ (long) val_long);
+ break;
+ case 'g':
+ fprintf_filtered (stream, local_hex_format_custom ("016l"),
+ (long) val_long);
+ break;
+ default:
+ abort ();
+ }
+#endif /* !PRINTF_HAS_LONG_LONG */
+}
+
+/* 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. */
+ memcpy ((char *) &low, valaddr, 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
+ memcpy (&low, valaddr+4, sizeof (low));
+ memcpy (&high, valaddr+0, sizeof (high));
+#else
+ memcpy (&low, valaddr+0, sizeof (low));
+ memcpy (&high, valaddr+4, 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) ? "%.9g" : "%.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;
+
+ /* FIXME: We should be not printing leading zeroes in most cases. */
+
+ fprintf_filtered (stream, local_hex_format_prefix ());
+#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);
+ }
+ fprintf_filtered (stream, local_hex_format_suffix ());
+}
+
+/* Called by various <lang>_val_print routines to print elements of an
+ array in the form "<elem1>, <elem2>, <elem3>, ...".
+
+ (FIXME?) Assumes array element separator is a comma, which is correct
+ for all languages currently handled.
+ (FIXME?) Some languages have a notation for repeated array elements,
+ perhaps we should try to use that notation when appropriate.
+ */
+
+void
+val_print_array_elements (type, valaddr, address, stream, format, deref_ref,
+ recurse, pretty, i)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+ unsigned int i;
+{
+ unsigned int things_printed = 0;
+ unsigned len;
+ struct type *elttype;
+ unsigned eltlen;
+ /* 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;
+
+ elttype = TYPE_TARGET_TYPE (type);
+ eltlen = TYPE_LENGTH (elttype);
+ len = TYPE_LENGTH (type) / eltlen;
+
+ for (; i < len && things_printed < print_max; i++)
+ {
+ if (i != 0)
+ {
+ if (prettyprint_arrays)
+ {
+ 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) &&
+ !memcmp (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, "...");
+ }
+}
+
+static void
+value_print_array_elements (val, stream, format, pretty)
+ value val;
+ FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ unsigned int things_printed = 0;
+ register unsigned int i, n, typelen;
+ /* Position of the array elem we are examining to see if it is repeated. */
+ unsigned int rep1;
+ /* Number of repetitions we have detected so far. */
+ unsigned int reps;
+
+ n = VALUE_REPETITIONS (val);
+ typelen = TYPE_LENGTH (VALUE_TYPE (val));
+ for (i = 0; i < n && things_printed < print_max; i++)
+ {
+ if (i != 0)
+ {
+ fprintf_filtered (stream, ", ");
+ }
+ wrap_here ("");
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < n && !memcmp (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, "...");
+ }
+}
+
+/* Print a string from the inferior, starting at ADDR and printing up to LEN
+ characters, to STREAM. If LEN is zero, printing stops at the first null
+ byte, otherwise printing proceeds (including null bytes) until either
+ print_max or LEN characters have been printed, whichever is smaller. */
+
+int
+val_print_string (addr, len, stream)
+ CORE_ADDR addr;
+ unsigned int len;
+ FILE *stream;
+{
+ int force_ellipsis = 0; /* Force ellipsis to be printed if nonzero. */
+ int errcode; /* Errno returned from bad reads. */
+ unsigned int fetchlimit; /* Maximum number of bytes to fetch. */
+ unsigned int nfetch; /* Bytes to fetch / bytes fetched. */
+ unsigned int chunksize; /* Size of each fetch, in bytes. */
+ int bufsize; /* Size of current fetch buffer. */
+ char *buffer = NULL; /* Dynamically growable fetch buffer. */
+ char *bufptr; /* Pointer to next available byte in buffer. */
+ char *limit; /* First location past end of fetch buffer. */
+ struct cleanup *old_chain = NULL; /* Top of the old cleanup chain. */
+ char peekchar; /* Place into which we can read one char. */
+
+ /* First we need to figure out the limit on the number of characters we are
+ going to attempt to fetch and print. This is actually pretty simple. If
+ LEN is nonzero, then the limit is the minimum of LEN and print_max. If
+ LEN is zero, then the limit is print_max. This is true regardless of
+ whether print_max is zero, UINT_MAX (unlimited), or something in between,
+ because finding the null byte (or available memory) is what actually
+ limits the fetch. */
+
+ fetchlimit = (len == 0 ? print_max : min (len, print_max));
+
+ /* Now decide how large of chunks to try to read in one operation. This
+ is also pretty simple. If LEN is nonzero, then we want fetchlimit bytes,
+ so we might as well read them all in one operation. If LEN is zero, we
+ are looking for a null terminator to end the fetching, so we might as
+ well read in blocks that are large enough to be efficient, but not so
+ large as to be slow if fetchlimit happens to be large. So we choose the
+ minimum of DEFAULT_PRINT_MAX and fetchlimit. */
+
+ chunksize = (len == 0 ? min (PRINT_MAX_DEFAULT, fetchlimit) : fetchlimit);
+
+ /* Loop until we either have all the characters to print, or we encounter
+ some error, such as bumping into the end of the address space. */
+
+ bufsize = 0;
+ do {
+ QUIT;
+ /* Figure out how much to fetch this time, and grow the buffer to fit. */
+ nfetch = min (chunksize, fetchlimit - bufsize);
+ bufsize += nfetch;
+ if (buffer == NULL)
+ {
+ buffer = (char *) xmalloc (bufsize);
+ bufptr = buffer;
+ }
+ else
+ {
+ discard_cleanups (old_chain);
+ buffer = (char *) xrealloc (buffer, bufsize);
+ bufptr = buffer + bufsize - nfetch;
+ }
+ old_chain = make_cleanup (free, buffer);
+
+ /* Read as much as we can. */
+ nfetch = target_read_memory_partial (addr, bufptr, nfetch, &errcode);
+ if (len != 0)
+ {
+ addr += nfetch;
+ bufptr += nfetch;
+ }
+ else
+ {
+ /* Scan this chunk for the null byte that terminates the string
+ to print. If found, we don't need to fetch any more. Note
+ that bufptr is explicitly left pointing at the next character
+ after the null byte, or at the next character after the end of
+ the buffer. */
+ limit = bufptr + nfetch;
+ do {
+ addr++;
+ bufptr++;
+ } while (bufptr < limit && *(bufptr - 1) != '\0');
+ }
+ } while (errcode == 0 /* no error */
+ && bufptr < buffer + fetchlimit /* no overrun */
+ && !(len == 0 && *(bufptr - 1) == '\0')); /* no null term */
+
+ /* We now have either successfully filled the buffer to fetchlimit, or
+ terminated early due to an error or finding a null byte when LEN is
+ zero. */
+
+ if (len == 0 && *(bufptr - 1) != '\0')
+ {
+ /* We didn't find a null terminator we were looking for. Attempt
+ to peek at the next character. If not successful, or it is not
+ a null byte, then force ellipsis to be printed. */
+ if (target_read_memory (addr, &peekchar, 1) != 0 || peekchar != '\0')
+ {
+ force_ellipsis = 1;
+ }
+ }
+ else if ((len != 0 && errcode != 0) || (len > bufptr - buffer))
+ {
+ /* Getting an error when we have a requested length, or fetching less
+ than the number of characters actually requested, always make us
+ print ellipsis. */
+ force_ellipsis = 1;
+ }
+
+ QUIT;
+
+ if (addressprint)
+ {
+ fputs_filtered (" ", stream);
+ }
+ LA_PRINT_STRING (stream, buffer, bufptr - buffer, force_ellipsis);
+
+ if (errcode != 0 && force_ellipsis)
+ {
+ if (errcode == EIO)
+ {
+ fprintf_filtered (stream,
+ " <Address 0x%lx out of bounds>",
+ (unsigned long) addr);
+ }
+ else
+ {
+ error ("Error reading memory address 0x%lx: %s.",
+ (unsigned long) addr,
+ safe_strerror (errcode));
+ }
+ }
+ fflush (stream);
+ do_cleanups (old_chain);
+ return (bufptr - buffer);
+}
+
+
+/* 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! */
+
+/* ARGSUSED */
+static void
+set_input_radix (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ set_input_radix_1 (from_tty, *(unsigned *)c->var);
+}
+
+/* ARGSUSED */
+static void
+set_input_radix_1 (from_tty, radix)
+ int from_tty;
+ unsigned radix;
+{
+ /* We don't currently disallow any input radix except 0 or 1, which don't
+ make any mathematical sense. In theory, we can deal with any input
+ radix greater than 1, even if we don't have unique digits for every
+ value from 0 to radix-1, but in practice we lose on large radix values.
+ We should either fix the lossage or restrict the radix range more.
+ (FIXME). */
+
+ if (radix < 2)
+ {
+ error ("Nonsense input radix ``decimal %u''; input radix unchanged.",
+ radix);
+ }
+ input_radix = radix;
+ if (from_tty)
+ {
+ printf_filtered ("Input radix now set to decimal %u, hex %x, octal %o.\n",
+ radix, radix, radix);
+ }
+}
+
+/* ARGSUSED */
+static void
+set_output_radix (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ set_output_radix_1 (from_tty, *(unsigned *)c->var);
+}
+
+static void
+set_output_radix_1 (from_tty, radix)
+ int from_tty;
+ unsigned radix;
+{
+ /* Validate the radix and disallow ones that we aren't prepared to
+ handle correctly, leaving the radix unchanged. */
+ switch (radix)
+ {
+ case 16:
+ output_format = 'x'; /* hex */
+ break;
+ case 10:
+ output_format = 0; /* decimal */
+ break;
+ case 8:
+ output_format = 'o'; /* octal */
+ break;
+ default:
+ error ("Unsupported output radix ``decimal %u''; output radix unchanged.",
+ radix);
+ }
+ output_radix = radix;
+ if (from_tty)
+ {
+ printf_filtered ("Output radix now set to decimal %u, hex %x, octal %o.\n",
+ radix, radix, radix);
+ }
+}
+
+/* Set both the input and output radix at once. Try to set the output radix
+ first, since it has the most restrictive range. An radix that is valid as
+ an output radix is also valid as an input radix.
+
+ It may be useful to have an unusual input radix. If the user wishes to
+ set an input radix that is not valid as an output radix, he needs to use
+ the 'set input-radix' command. */
+
+static void
+set_radix (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ unsigned radix;
+
+ radix = (arg == NULL) ? 10 : parse_and_eval_address (arg);
+ set_output_radix_1 (0, radix);
+ set_input_radix_1 (0, radix);
+ if (from_tty)
+ {
+ printf_filtered ("Input and output radices now set to decimal %u, hex %x, octal %o.\n",
+ radix, radix, radix);
+ }
+}
+
+/* Show both the input and output radices. */
+
+/*ARGSUSED*/
+static void
+show_radix (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (from_tty)
+ {
+ if (input_radix == output_radix)
+ {
+ printf_filtered ("Input and output radices set to decimal %u, hex %x, octal %o.\n",
+ input_radix, input_radix, input_radix);
+ }
+ else
+ {
+ printf_filtered ("Input radix set to decimal %u, hex %x, octal %o.\n",
+ input_radix, input_radix, input_radix);
+ printf_filtered ("Output radix set to decimal %u, hex %x, octal %o.\n",
+ output_radix, output_radix, output_radix);
+ }
+ }
+}
+
+
+/*ARGSUSED*/
+static void
+set_print (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf (
+"\"set print\" must be followed by the name of a print subcommand.\n");
+ help_list (setprintlist, "set print ", -1, stdout);
+}
+
+/*ARGSUSED*/
+static void
+show_print (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ cmd_show_list (showprintlist, from_tty, "");
+}
+
+void
+_initialize_valprint ()
+{
+ struct cmd_list_element *c;
+
+ add_prefix_cmd ("print", no_class, set_print,
+ "Generic command for setting how things print.",
+ &setprintlist, "set print ", 0, &setlist);
+ add_alias_cmd ("p", "print", no_class, 1, &setlist);
+ /* prefer set print to set prompt */
+ add_alias_cmd ("pr", "print", no_class, 1, &setlist);
+
+ add_prefix_cmd ("print", no_class, show_print,
+ "Generic command for showing print settings.",
+ &showprintlist, "show print ", 0, &showlist);
+ add_alias_cmd ("p", "print", no_class, 1, &showlist);
+ add_alias_cmd ("pr", "print", no_class, 1, &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("elements", no_class, var_uinteger, (char *)&print_max,
+ "Set limit on string chars or array elements to print.\n\
+\"set print elements 0\" causes there to be no limit.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("repeats", no_class, var_uinteger,
+ (char *)&repeat_count_threshold,
+ "Set threshold for repeated print elements.\n\
+\"set print repeats 0\" causes all elements to be individually printed.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("pretty", class_support, var_boolean,
+ (char *)&prettyprint_structs,
+ "Set prettyprinting of structures.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("union", class_support, var_boolean, (char *)&unionprint,
+ "Set printing of unions interior to structures.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("array", class_support, var_boolean,
+ (char *)&prettyprint_arrays,
+ "Set prettyprinting of arrays.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("address", class_support, var_boolean, (char *)&addressprint,
+ "Set printing of addresses.",
+ &setprintlist),
+ &showprintlist);
+
+ 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.sfunc = 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.sfunc = set_output_radix;
+
+ /* The "set radix" and "show radix" commands are special in that they are
+ like normal set and show commands but allow two normally independent
+ variables to be either set or shown with a single command. So the
+ usual add_set_cmd() and add_show_from_set() commands aren't really
+ appropriate. */
+ add_cmd ("radix", class_support, set_radix,
+ "Set default input and output number radices.\n\
+Use 'set input-radix' or 'set output-radix' to independently set each.\n\
+Without an argument, sets both radices back to the default value of 10.",
+ &setlist);
+ add_cmd ("radix", class_support, show_radix,
+ "Show the default input and output number radices.\n\
+Use 'show input-radix' or 'show output-radix' to independently show each.",
+ &showlist);
+
+ /* Give people the defaults which they are used to. */
+ prettyprint_structs = 0;
+ prettyprint_arrays = 0;
+ unionprint = 1;
+ addressprint = 1;
+ print_max = PRINT_MAX_DEFAULT;
+}
diff --git a/gnu/usr.bin/gdb/gdb/valprint.h b/gnu/usr.bin/gdb/gdb/valprint.h
new file mode 100644
index 000000000000..5918def07e68
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/valprint.h
@@ -0,0 +1,40 @@
+/* Declarations for value printing routines for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+extern int prettyprint_arrays; /* Controls pretty printing of arrays. */
+extern int prettyprint_structs; /* Controls pretty printing of structures */
+extern int prettyprint_arrays; /* Controls pretty printing of arrays. */
+
+extern int vtblprint; /* Controls printing of vtbl's */
+extern int unionprint; /* Controls printing of nested unions. */
+extern int addressprint; /* Controls pretty printing of addresses. */
+extern int objectprint; /* Controls looking up an object's derived type
+ using what we find in its vtables. */
+
+extern unsigned int print_max; /* Max # of chars for strings/vectors */
+extern int output_format;
+
+extern void
+val_print_array_elements PARAMS ((struct type *, char *, CORE_ADDR, FILE *,
+ int, int, int, enum val_prettyprint, int));
+
+extern void
+val_print_type_code_int PARAMS ((struct type *, char *, FILE *));
+
diff --git a/gnu/usr.bin/gdb/gdb/value.h b/gnu/usr.bin/gdb/gdb/value.h
new file mode 100644
index 000000000000..b8e16761e5d6
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/value.h
@@ -0,0 +1,502 @@
+/* Definitions for values of C expressions, for GDB.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 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 internal 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.
+ For BITS_BIG_ENDIAN=0 targets, it is the position of the LSB.
+ For BITS_BIG_ENDIAN=1 targets, it is the position of the MSB. */
+ 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 CC_HAS_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 PARAMS ((value val));
+
+#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) \
+{ COERCE_REF (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;
+};
+
+/* Pointer to member function. Depends on compiler implementation. */
+
+#define METHOD_PTR_IS_VIRTUAL(ADDR) ((ADDR) & 0x80000000)
+#define METHOD_PTR_FROM_VOFFSET(OFFSET) (0x80000000 + (OFFSET))
+#define METHOD_PTR_TO_VOFFSET(ADDR) (~0x80000000 & (ADDR))
+
+
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+
+#ifdef __STDC__
+struct frame_info;
+struct fn_field;
+#endif
+
+extern void
+print_address_demangle PARAMS ((CORE_ADDR, FILE *, int));
+
+extern LONGEST
+value_as_long PARAMS ((value val));
+
+extern double
+value_as_double PARAMS ((value val));
+
+extern CORE_ADDR
+value_as_pointer PARAMS ((value val));
+
+extern LONGEST
+unpack_long PARAMS ((struct type *type, char *valaddr));
+
+extern double
+unpack_double PARAMS ((struct type *type, char *valaddr, int *invp));
+
+extern CORE_ADDR unpack_pointer PARAMS ((struct type *type, char *valaddr));
+
+extern LONGEST unpack_field_as_long PARAMS ((struct type *type, char *valaddr,
+ int fieldno));
+
+extern value value_from_longest PARAMS ((struct type *type, LONGEST num));
+
+extern value value_from_double PARAMS ((struct type *type, double num));
+
+extern value value_at PARAMS ((struct type *type, CORE_ADDR addr));
+
+extern value value_at_lazy PARAMS ((struct type *type, CORE_ADDR addr));
+
+/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */
+extern value value_from_register PARAMS ((struct type *type, int regnum,
+ struct frame_info * frame));
+
+extern value value_of_variable PARAMS ((struct symbol *var, struct block *b));
+
+extern value value_of_register PARAMS ((int regnum));
+
+extern int symbol_read_needs_frame PARAMS ((struct symbol *));
+
+/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */
+extern value read_var_value PARAMS ((struct symbol *var,
+ struct frame_info *frame));
+
+/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */
+extern value locate_var_value PARAMS ((struct symbol *var,
+ struct frame_info *frame));
+
+extern value allocate_value PARAMS ((struct type *type));
+
+extern value allocate_repeat_value PARAMS ((struct type *type, int count));
+
+extern value value_mark PARAMS ((void));
+
+extern void value_free_to_mark PARAMS ((value mark));
+
+extern value value_string PARAMS ((char *ptr, int len));
+
+extern value value_array PARAMS ((int lowbound, int highbound,
+ value *elemvec));
+
+extern value value_concat PARAMS ((value arg1, value arg2));
+
+extern value value_binop PARAMS ((value arg1, value arg2, enum exp_opcode op));
+
+extern value value_add PARAMS ((value arg1, value arg2));
+
+extern value value_sub PARAMS ((value arg1, value arg2));
+
+extern value value_coerce_array PARAMS ((value arg1));
+
+extern value value_coerce_function PARAMS ((value arg1));
+
+extern value value_ind PARAMS ((value arg1));
+
+extern value value_addr PARAMS ((value arg1));
+
+extern value value_assign PARAMS ((value toval, value fromval));
+
+extern value value_neg PARAMS ((value arg1));
+
+extern value value_complement PARAMS ((value arg1));
+
+extern value value_struct_elt PARAMS ((value *argp, value *args, char *name,
+ int *static_memfuncp, char *err));
+
+extern value value_struct_elt_for_reference PARAMS ((struct type *domain,
+ int offset,
+ struct type *curtype,
+ char *name,
+ struct type *intype));
+
+extern value value_field PARAMS ((value arg1, int fieldno));
+
+extern value value_primitive_field PARAMS ((value arg1, int offset,
+ int fieldno,
+ struct type *arg_type));
+
+extern value value_cast PARAMS ((struct type *type, value arg2));
+
+extern value value_zero PARAMS ((struct type *type, enum lval_type lv));
+
+extern value value_repeat PARAMS ((value arg1, int count));
+
+extern value value_subscript PARAMS ((value array, value idx));
+
+extern value value_from_vtable_info PARAMS ((value arg, struct type *type));
+
+extern value value_being_returned PARAMS ((struct type *valtype,
+ char retbuf[REGISTER_BYTES],
+ int struct_return));
+
+extern int
+using_struct_return PARAMS ((value function, CORE_ADDR funcaddr,
+ struct type *value_type, int gcc_p));
+
+extern void
+set_return_value PARAMS ((value val));
+
+extern value
+evaluate_expression PARAMS ((struct expression *exp));
+
+extern value
+evaluate_type PARAMS ((struct expression *exp));
+
+extern value
+parse_and_eval PARAMS ((char *exp));
+
+extern value
+parse_to_comma_and_eval PARAMS ((char **expp));
+
+extern struct type *
+parse_and_eval_type PARAMS ((char *p, int length));
+
+extern CORE_ADDR
+parse_and_eval_address PARAMS ((char *exp));
+
+extern CORE_ADDR
+parse_and_eval_address_1 PARAMS ((char **expptr));
+
+extern value
+access_value_history PARAMS ((int num));
+
+extern value
+value_of_internalvar PARAMS ((struct internalvar *var));
+
+extern void
+set_internalvar PARAMS ((struct internalvar *var, value val));
+
+extern void
+set_internalvar_component PARAMS ((struct internalvar *var, int offset,
+ int bitpos, int bitsize,
+ value newvalue));
+
+extern struct internalvar *
+lookup_internalvar PARAMS ((char *name));
+
+extern int
+value_equal PARAMS ((value arg1, value arg2));
+
+extern int
+value_less PARAMS ((value arg1, value arg2));
+
+extern int
+value_logical_not PARAMS ((value arg1));
+
+/* C++ */
+
+extern value
+value_of_this PARAMS ((int complain));
+
+extern value
+value_x_binop PARAMS ((value arg1, value arg2, enum exp_opcode op,
+ enum exp_opcode otherop));
+
+extern value
+value_x_unop PARAMS ((value arg1, enum exp_opcode op));
+
+extern value
+value_fn_field PARAMS ((value *arg1p, struct fn_field *f, int j,
+ struct type* type, int offset));
+
+extern value
+value_virtual_fn_field PARAMS ((value *arg1p, struct fn_field *f, int j,
+ struct type *type, int offset));
+
+extern int
+binop_user_defined_p PARAMS ((enum exp_opcode op, value arg1, value arg2));
+
+extern int
+unop_user_defined_p PARAMS ((enum exp_opcode op, value arg1));
+
+extern int
+destructor_name_p PARAMS ((const char *name, const struct type *type));
+
+#define value_free(val) free ((PTR)val)
+
+extern void
+free_all_values PARAMS ((void));
+
+extern void
+release_value PARAMS ((value val));
+
+extern int
+record_latest_value PARAMS ((value val));
+
+extern void
+registers_changed PARAMS ((void));
+
+extern void
+read_register_bytes PARAMS ((int regbyte, char *myaddr, int len));
+
+extern void
+write_register_bytes PARAMS ((int regbyte, char *myaddr, int len));
+
+extern void
+read_register_gen PARAMS ((int regno, char *myaddr));
+
+extern CORE_ADDR
+read_register PARAMS ((int regno));
+
+extern void
+write_register PARAMS ((int regno, LONGEST val));
+
+extern void
+supply_register PARAMS ((int regno, char *val));
+
+/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */
+extern void
+get_saved_register PARAMS ((char *raw_buffer, int *optimized,
+ CORE_ADDR *addrp, struct frame_info *frame,
+ int regnum, enum lval_type *lval));
+
+extern void
+modify_field PARAMS ((char *addr, LONGEST fieldval, int bitpos, int bitsize));
+
+extern void
+type_print PARAMS ((struct type *type, char *varstring, FILE *stream,
+ int show));
+
+extern char *
+baseclass_addr PARAMS ((struct type *type, int index, char *valaddr,
+ value *valuep, int *errp));
+
+extern void
+print_longest PARAMS ((FILE *stream, int format, int use_local,
+ LONGEST value));
+
+extern void
+print_floating PARAMS ((char *valaddr, struct type *type, FILE *stream));
+
+extern int
+value_print PARAMS ((value val, FILE *stream, int format,
+ enum val_prettyprint pretty));
+
+extern int
+val_print PARAMS ((struct type *type, char *valaddr, CORE_ADDR address,
+ FILE *stream, int format, int deref_ref,
+ int recurse, enum val_prettyprint pretty));
+
+extern int
+val_print_string PARAMS ((CORE_ADDR addr, unsigned int len, FILE *stream));
+
+/* FIXME: Assumes equivalence of "struct frame_info *" and "FRAME" */
+extern void
+print_variable_value PARAMS ((struct symbol *var, struct frame_info *frame,
+ FILE *stream));
+
+extern value
+value_arg_coerce PARAMS ((value));
+
+extern int
+check_field PARAMS ((value, const char *));
+
+extern void
+c_typedef_print PARAMS ((struct type *type, struct symbol *new, FILE *stream));
+
+extern char *
+internalvar_name PARAMS ((struct internalvar *var));
+
+extern void
+clear_value_history PARAMS ((void));
+
+extern void
+clear_internalvars PARAMS ((void));
+
+/* From values.c */
+
+extern value
+value_copy PARAMS ((value));
+
+extern int
+baseclass_offset PARAMS ((struct type *, int, value, int));
+
+/* From valops.c */
+
+extern value
+call_function_by_hand PARAMS ((value, int, value *));
+
+#endif /* !defined (VALUE_H) */
diff --git a/gnu/usr.bin/gdb/gdb/values.c b/gnu/usr.bin/gdb/gdb/values.c
new file mode 100644
index 000000000000..a592f9eeca98
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/values.c
@@ -0,0 +1,1502 @@
+/* Low level packing and unpacking of values for GDB, the GNU Debugger.
+ Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "defs.h"
+#include <string.h>
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "demangle.h"
+
+/* Local function prototypes. */
+
+static value
+value_headof PARAMS ((value, struct type *, struct type *));
+
+static void
+show_values PARAMS ((char *, int));
+
+static void
+show_convenience PARAMS ((char *, int));
+
+/* 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 */
+
+/* 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;
+}
+
+/* Return a mark in the value chain. All values allocated after the
+ mark is obtained (except for those released) are subject to being freed
+ if a subsequent value_free_to_mark is passed the mark. */
+value
+value_mark ()
+{
+ return all_values;
+}
+
+/* Free all values allocated since MARK was obtained by value_mark
+ (except for those released). */
+void
+value_free_to_mark (mark)
+ value mark;
+{
+ value val, next;
+
+ for (val = all_values; val && val != mark; val = next)
+ {
+ next = VALUE_NEXT (val);
+ value_free (val);
+ }
+ all_values = 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. */
+
+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))
+ {
+ memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS_RAW (arg),
+ TYPE_LENGTH (VALUE_TYPE (arg))
+ * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
+ }
+ return val;
+}
+
+/* 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)
+ {
+ 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));
+ memset (new->values, 0, sizeof new->values);
+ new->next = value_history_chain;
+ value_history_chain = new;
+ }
+
+ value_history_chain->values[i] = val;
+
+ /* We don't want this value to have anything to do with the inferior anymore.
+ In particular, "set $1 = 50" should not affect the variable from which
+ the value was taken, and fast watchpoints should be able to assume that
+ a value on the value history never changes. */
+ if (VALUE_LAZY (val))
+ value_fetch_lazy (val);
+ VALUE_LVAL (val) = not_lval;
+ 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]) != NULL)
+ free ((PTR)val);
+ next = value_history_chain->next;
+ free ((PTR)value_history_chain);
+ value_history_chain = next;
+ }
+ value_history_count = 0;
+}
+
+static void
+show_values (num_exp, from_tty)
+ char *num_exp;
+ int from_tty;
+{
+ register int i;
+ register value val;
+ static int num = 1;
+
+ if (num_exp)
+ {
+ /* "info history +" should print from the stored position.
+ "info history <exp>" should print around value number <exp>. */
+ if (num_exp[0] != '+' || num_exp[1] != '\0')
+ 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';
+ }
+}
+
+/* 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 (STREQ (var->name, name))
+ return var;
+
+ var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
+ var->name = concat (name, NULL);
+ 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, value_as_long (newval),
+ bitpos, bitsize);
+ else
+ memcpy (addr, VALUE_CONTENTS (newval), 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 ((PTR)var->value);
+ var->value = value_copy (val);
+ /* Force the value to be fetched from the target now, to avoid problems
+ later when this internalvar is referenced and the target is gone or
+ has changed. */
+ if (VALUE_LAZY (var->value))
+ value_fetch_lazy (var->value);
+ 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 ((PTR)var->name);
+ free ((PTR)var->value);
+ free ((PTR)var);
+ }
+}
+
+static void
+show_convenience (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ 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)
+ {
+ varseen = 1;
+ }
+ printf_filtered ("$%s = ", var->name);
+ value_print (var->value, stdout, 0, Val_pretty_default);
+ printf_filtered ("\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");
+}
+
+/* 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;
+}
+/* Extract a value as a C pointer.
+ Does not deallocate the value. */
+CORE_ADDR
+value_as_pointer (val)
+ value val;
+{
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+#if 0
+ /* ADDR_BITS_REMOVE is wrong if we are being called for a
+ non-address (e.g. argument to "signal", "info break", etc.), or
+ for pointers to char, in which the low bits *are* significant. */
+ return ADDR_BITS_REMOVE(value_as_long (val));
+#else
+ return value_as_long (val);
+#endif
+}
+
+/* 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. */
+
+/* FIXME: This should be rewritten as a switch statement for speed and
+ ease of comprehension. */
+
+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_BOOL)
+ code = TYPE_CODE_INT;
+ if (code == TYPE_CODE_FLT)
+ {
+ if (len == sizeof (float))
+ {
+ float retval;
+ memcpy (&retval, valaddr, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (double))
+ {
+ double retval;
+ memcpy (&retval, valaddr, 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 || code == TYPE_CODE_CHAR) && nosign)
+ {
+ return extract_unsigned_integer (valaddr, len);
+ }
+ else if (code == TYPE_CODE_INT || code == TYPE_CODE_CHAR)
+ {
+ return extract_signed_integer (valaddr, len);
+ }
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+ else if (code == TYPE_CODE_PTR || code == TYPE_CODE_REF)
+ {
+ return extract_address (valaddr, len);
+ }
+ 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;
+ memcpy (&retval, valaddr, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+
+ if (len == sizeof (double))
+ {
+ double retval;
+ memcpy (&retval, valaddr, sizeof (retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
+ return retval;
+ }
+ else
+ {
+ error ("Unexpected type of floating point number.");
+ return 0; /* Placate lint. */
+ }
+ }
+ else if (nosign) {
+ /* Unsigned -- be sure we compensate for signed LONGEST. */
+ return (unsigned LONGEST) unpack_long (type, valaddr);
+ } else {
+ /* Signed -- we are OK with unpack_long. */
+ return unpack_long (type, valaddr);
+ }
+}
+
+/* Unpack raw data (copied from debugee, target byte order) at VALADDR
+ as a CORE_ADDR, assuming the raw data is described by type TYPE.
+ 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_pointer() 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. */
+
+CORE_ADDR
+unpack_pointer (type, valaddr)
+ struct type *type;
+ char *valaddr;
+{
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+ return unpack_long (type, valaddr);
+}
+
+/* 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_longest (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
+ memcpy (VALUE_CONTENTS_RAW (v), VALUE_CONTENTS_RAW (arg1) + offset,
+ 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));
+}
+
+/* Return a non-virtual function as a value.
+ F is the list of member functions which contains the desired method.
+ J is an index into F which provides the desired method. */
+
+value
+value_fn_field (arg1p, f, j, type, offset)
+ value *arg1p;
+ struct fn_field *f;
+ int j;
+ struct type *type;
+ int offset;
+{
+ register value v;
+ register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
+ struct symbol *sym;
+
+ sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
+ 0, VAR_NAMESPACE, 0, NULL);
+ if (! sym) error ("Internal error: could not find physical method named %s",
+ TYPE_FN_FIELD_PHYSNAME (f, j));
+
+ v = allocate_value (ftype);
+ VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+ VALUE_TYPE (v) = ftype;
+
+ if (arg1p)
+ {
+ if (type != VALUE_TYPE (*arg1p))
+ *arg1p = value_ind (value_cast (lookup_pointer_type (type),
+ value_addr (*arg1p)));
+
+ /* Move the `this' pointer according to the offset.
+ VALUE_OFFSET (*arg1p) += offset;
+ */
+ }
+
+ return v;
+}
+
+/* Return a virtual function as a value.
+ ARG1 is the object which provides the virtual function
+ table pointer. *ARG1P 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.
+
+ TYPE is the type in which F is located. */
+value
+value_virtual_fn_field (arg1p, f, j, type, offset)
+ value *arg1p;
+ struct fn_field *f;
+ int j;
+ struct type *type;
+ int offset;
+{
+ value arg1 = *arg1p;
+ /* 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_longest (builtin_type_int,
+ (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
+ struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
+ struct type *context;
+ if (fcontext == NULL)
+ /* We don't have an fcontext (e.g. the program was compiled with
+ g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
+ This won't work right for multiple inheritance, but at least we
+ should do as well as GDB 3.x did. */
+ fcontext = TYPE_VPTR_BASETYPE (type);
+ context = lookup_pointer_type (fcontext);
+ /* Now context is a pointer to the basetype containing the vtbl. */
+ if (TYPE_TARGET_TYPE (context) != VALUE_TYPE (arg1))
+ arg1 = value_ind (value_cast (context, value_addr (arg1)));
+
+ context = VALUE_TYPE (arg1);
+ /* Now context is the basetype containing the vtbl. */
+
+ /* 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)
+ 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_primitive_field (arg1, 0,
+ TYPE_VPTR_FIELDNO (context),
+ TYPE_VPTR_BASETYPE (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))/* + offset*/;
+
+ 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));
+
+ *arg1p = arg1;
+ return vfn;
+}
+
+/* ARG is a pointer to an object we know to be at least
+ a DTYPE. BTYPE is the most derived basetype that has
+ already been searched (and need not be searched again).
+ After looking at the vtables between BTYPE and DTYPE,
+ return the most derived type we find. The caller must
+ be satisfied when the return value == DTYPE.
+
+ FIXME-tiemann: should work with dossier entries as well. */
+
+static value
+value_headof (in_arg, btype, dtype)
+ value in_arg;
+ struct type *btype, *dtype;
+{
+ /* First collect the vtables we must look at for this object. */
+ /* FIXME-tiemann: right now, just look at top-most vtable. */
+ value arg, vtbl, entry, best_entry = 0;
+ int i, nelems;
+ int offset, best_offset = 0;
+ struct symbol *sym;
+ CORE_ADDR pc_for_sym;
+ char *demangled_name;
+ struct minimal_symbol *msymbol;
+
+ btype = TYPE_VPTR_BASETYPE (dtype);
+ check_stub_type (btype);
+ arg = in_arg;
+ if (btype != dtype)
+ arg = value_cast (lookup_pointer_type (btype), arg);
+ vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype)));
+
+ /* Check that VTBL looks like it points to a virtual function table. */
+ msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
+ if (msymbol == NULL
+ || !VTBL_PREFIX_P (demangled_name = SYMBOL_NAME (msymbol)))
+ {
+ /* If we expected to find a vtable, but did not, let the user
+ know that we aren't happy, but don't throw an error.
+ FIXME: there has to be a better way to do this. */
+ struct type *error_type = (struct type *)xmalloc (sizeof (struct type));
+ memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
+ TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
+ VALUE_TYPE (in_arg) = error_type;
+ return in_arg;
+ }
+
+ /* Now search through the virtual function table. */
+ entry = value_ind (vtbl);
+ nelems = longest_to_int (value_as_long (value_field (entry, 2)));
+ for (i = 1; i <= nelems; i++)
+ {
+ entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
+ (LONGEST) i));
+ offset = longest_to_int (value_as_long (value_field (entry, 0)));
+ /* If we use '<=' we can handle single inheritance
+ * where all offsets are zero - just use the first entry found. */
+ if (offset <= best_offset)
+ {
+ best_offset = offset;
+ best_entry = entry;
+ }
+ }
+ /* Move the pointer according to BEST_ENTRY's offset, and figure
+ out what type we should return as the new pointer. */
+ if (best_entry == 0)
+ {
+ /* An alternative method (which should no longer be necessary).
+ * But we leave it in for future use, when we will hopefully
+ * have optimizes the vtable to use thunks instead of offsets. */
+ /* Use the name of vtable itself to extract a base type. */
+ demangled_name += 4; /* Skip _vt$ prefix. */
+ }
+ else
+ {
+ pc_for_sym = value_as_pointer (value_field (best_entry, 2));
+ sym = find_pc_function (pc_for_sym);
+ demangled_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ANSI);
+ *(strchr (demangled_name, ':')) = '\0';
+ }
+ sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
+ if (sym == NULL)
+ error ("could not find type declaration for `%s'", demangled_name);
+ if (best_entry)
+ {
+ free (demangled_name);
+ arg = value_add (value_cast (builtin_type_int, arg),
+ value_field (best_entry, 0));
+ }
+ else arg = in_arg;
+ VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
+ return arg;
+}
+
+/* ARG is a pointer object of type TYPE. If TYPE has virtual
+ function tables, probe ARG's tables (including the vtables
+ of its baseclasses) to figure out the most derived type that ARG
+ could actually be a pointer to. */
+
+value
+value_from_vtable_info (arg, type)
+ value arg;
+ struct type *type;
+{
+ /* Take care of preliminaries. */
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ fill_in_vptr_fieldno (type);
+ if (TYPE_VPTR_FIELDNO (type) < 0 || VALUE_REPEATED (arg))
+ return 0;
+
+ return value_headof (arg, 0, type);
+}
+
+/* Return true if the INDEXth field of TYPE is a virtual baseclass
+ pointer which is for the base class whose type is BASECLASS. */
+
+static int
+vb_match (type, index, basetype)
+ struct type *type;
+ int index;
+ struct type *basetype;
+{
+ struct type *fieldtype;
+ char *name = TYPE_FIELD_NAME (type, index);
+ char *field_class_name = NULL;
+
+ if (*name != '_')
+ return 0;
+ /* gcc 2.4 uses _vb$. */
+ if (name[1] == 'v' && name[2] == 'b' && name[3] == CPLUS_MARKER)
+ field_class_name = name + 4;
+ /* gcc 2.5 will use __vb_. */
+ if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
+ field_class_name = name + 5;
+
+ if (field_class_name == NULL)
+ /* This field is not a virtual base class pointer. */
+ return 0;
+
+ /* It's a virtual baseclass pointer, now we just need to find out whether
+ it is for this baseclass. */
+ fieldtype = TYPE_FIELD_TYPE (type, index);
+ if (fieldtype == NULL
+ || TYPE_CODE (fieldtype) != TYPE_CODE_PTR)
+ /* "Can't happen". */
+ return 0;
+
+ /* What we check for is that either the types are equal (needed for
+ nameless types) or have the same name. This is ugly, and a more
+ elegant solution should be devised (which would probably just push
+ the ugliness into symbol reading unless we change the stabs format). */
+ if (TYPE_TARGET_TYPE (fieldtype) == basetype)
+ return 1;
+
+ if (TYPE_NAME (basetype) != NULL
+ && TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL
+ && STREQ (TYPE_NAME (basetype),
+ TYPE_NAME (TYPE_TARGET_TYPE (fieldtype))))
+ return 1;
+ return 0;
+}
+
+/* Compute the offset of the baseclass which is
+ the INDEXth baseclass of class TYPE, for a value ARG,
+ wih extra offset of OFFSET.
+ The result is the offste of the baseclass value relative
+ to (the address of)(ARG) + OFFSET.
+
+ -1 is returned on error. */
+
+int
+baseclass_offset (type, index, arg, offset)
+ struct type *type;
+ int index;
+ value arg;
+ int offset;
+{
+ 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);
+
+ /* First look for the virtual baseclass pointer
+ in the fields. */
+ for (i = n_baseclasses; i < len; i++)
+ {
+ if (vb_match (type, i, basetype))
+ {
+ CORE_ADDR addr
+ = unpack_pointer (TYPE_FIELD_TYPE (type, i),
+ VALUE_CONTENTS (arg) + VALUE_OFFSET (arg)
+ + offset
+ + (TYPE_FIELD_BITPOS (type, i) / 8));
+
+ if (VALUE_LVAL (arg) != lval_memory)
+ return -1;
+
+ return addr -
+ (LONGEST) (VALUE_ADDRESS (arg) + VALUE_OFFSET (arg) + offset);
+ }
+ }
+ /* Not in the fields, so try looking through the baseclasses. */
+ for (i = index+1; i < n_baseclasses; i++)
+ {
+ int boffset =
+ baseclass_offset (type, i, arg, offset);
+ if (boffset)
+ return boffset;
+ }
+ /* Not found. */
+ return -1;
+ }
+
+ /* Baseclass is easily computed. */
+ return TYPE_BASECLASS_BITPOS (type, index) / 8;
+}
+
+/* Compute the address of the baseclass which is
+ the INDEXth baseclass of class TYPE. The TYPE base
+ of the object is at VALADDR.
+
+ If ERRP is non-NULL, set *ERRP to be the errno code of any error,
+ or 0 if no error. In that case the return value is not the address
+ of the baseclasss, but the address which could not be read
+ successfully. */
+
+/* FIXME Fix remaining uses of baseclass_addr to use baseclass_offset */
+
+char *
+baseclass_addr (type, index, valaddr, valuep, errp)
+ struct type *type;
+ int index;
+ char *valaddr;
+ value *valuep;
+ int *errp;
+{
+ struct type *basetype = TYPE_BASECLASS (type, index);
+
+ if (errp)
+ *errp = 0;
+
+ 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);
+
+ /* First look for the virtual baseclass pointer
+ in the fields. */
+ for (i = n_baseclasses; i < len; i++)
+ {
+ if (vb_match (type, i, basetype))
+ {
+ value val = allocate_value (basetype);
+ CORE_ADDR addr;
+ int status;
+
+ addr
+ = unpack_pointer (TYPE_FIELD_TYPE (type, i),
+ valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
+
+ status = target_read_memory (addr,
+ VALUE_CONTENTS_RAW (val),
+ TYPE_LENGTH (basetype));
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = addr;
+
+ if (status != 0)
+ {
+ if (valuep)
+ *valuep = NULL;
+ release_value (val);
+ value_free (val);
+ if (errp)
+ *errp = status;
+ return (char *)addr;
+ }
+ else
+ {
+ if (valuep)
+ *valuep = val;
+ return (char *) VALUE_CONTENTS (val);
+ }
+ }
+ }
+ /* 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, errp);
+ 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;
+}
+
+/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
+ VALADDR.
+
+ Extracting bits depends on endianness of the machine. Compute the
+ number of least significant bits to discard. For big endian machines,
+ we compute the total number of bits in the anonymous object, subtract
+ off the bit count from the MSB of the object to the MSB of the
+ bitfield, then the size of the bitfield, which leaves the LSB discard
+ count. For little endian machines, the discard count is simply the
+ number of bits from the LSB of the anonymous object to the LSB of the
+ bitfield.
+
+ If the field is signed, we also do sign extension. */
+
+LONGEST
+unpack_field_as_long (type, valaddr, fieldno)
+ struct type *type;
+ char *valaddr;
+ int fieldno;
+{
+ unsigned LONGEST val;
+ unsigned LONGEST valmask;
+ int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+ int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ int lsbcount;
+
+ val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val));
+
+ /* Extract bits. See comment above. */
+
+#if BITS_BIG_ENDIAN
+ lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
+#else
+ lsbcount = (bitpos % 8);
+#endif
+ val >>= lsbcount;
+
+ /* If the field does not entirely fill a LONGEST, then zero the sign bits.
+ If the field is signed, and is negative, then sign extend. */
+
+ if ((bitsize > 0) && (bitsize < 8 * sizeof (val)))
+ {
+ valmask = (((unsigned LONGEST) 1) << bitsize) - 1;
+ val &= valmask;
+ if (!TYPE_UNSIGNED (TYPE_FIELD_TYPE (type, fieldno)))
+ {
+ if (val & (valmask ^ (valmask >> 1)))
+ {
+ val |= ~valmask;
+ }
+ }
+ }
+ return (val);
+}
+
+/* Modify the value of a bitfield. ADDR points to a block of memory in
+ target byte order; the bitfield starts in the byte pointed to. FIELDVAL
+ is the desired value of the field, in host byte order. BITPOS and BITSIZE
+ indicate which bits (in target bit order) comprise the bitfield. */
+
+void
+modify_field (addr, fieldval, bitpos, bitsize)
+ char *addr;
+ LONGEST fieldval;
+ int bitpos, bitsize;
+{
+ LONGEST oword;
+
+ /* Reject values too big to fit in the field in question,
+ otherwise adjoining fields may be corrupted. */
+ if (bitsize < (8 * sizeof (fieldval))
+ && 0 != (fieldval & ~((1<<bitsize)-1)))
+ {
+ /* FIXME: would like to include fieldval in the message, but
+ we don't have a sprintf_longest. */
+ error ("Value does not fit in %d bits.", bitsize);
+ }
+
+ oword = extract_signed_integer (addr, sizeof oword);
+
+ /* Shifting for bit field depends on endianness of the target machine. */
+#if BITS_BIG_ENDIAN
+ bitpos = sizeof (oword) * 8 - bitpos - bitsize;
+#endif
+
+ /* Mask out old value, while avoiding shifts >= size of oword */
+ if (bitsize < 8 * sizeof (oword))
+ oword &= ~(((((unsigned LONGEST)1) << bitsize) - 1) << bitpos);
+ else
+ oword &= ~((~(unsigned LONGEST)0) << bitpos);
+ oword |= fieldval << bitpos;
+
+ store_signed_integer (addr, sizeof oword, oword);
+}
+
+/* Convert C numbers into newly allocated values */
+
+value
+value_from_longest (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);
+
+ switch (code)
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ store_signed_integer (VALUE_CONTENTS_RAW (val), len, num);
+ break;
+
+ case TYPE_CODE_REF:
+ case TYPE_CODE_PTR:
+ /* This assumes that all pointers of a given length
+ have the same form. */
+ store_address (VALUE_CONTENTS_RAW (val), len, (CORE_ADDR) num);
+ break;
+
+ default:
+ error ("Unexpected type encountered for integer constant.");
+ }
+ 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;
+}
+
+/* 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. */
+/* As of about 31 Mar 93, GCC was changed to be compatible with the
+ native compiler. GCC 2.3.3 was the last release that did it the
+ old way. Since gcc2_compiled was not changed, we have no
+ way to correctly win in all cases, so we just do the right thing
+ for gcc1 and for gcc2 after this change. Thus it loses for gcc
+ 2.0-2.3.3. This is somewhat unfortunate, but changing gcc2_compiled
+ would cause more chaos than dealing with some struct returns being
+ handled wrong. */
+#if !defined (USE_STRUCT_CONVENTION)
+#define USE_STRUCT_CONVENTION(gcc_p, type)\
+ (!((gcc_p == 1) && (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) /* FIXME, implement struct return. */
+ error ("GDB does not support specifying a struct or union return value.");
+
+ /* 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);
+ }
+}
+
+void
+_initialize_values ()
+{
+ add_cmd ("convenience", no_class, show_convenience,
+ "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\".",
+ &showlist);
+
+ add_cmd ("values", no_class, show_values,
+ "Elements of value history around item number IDX (or last ten).",
+ &showlist);
+}
diff --git a/gnu/usr.bin/gdb/gdb/version.c b/gnu/usr.bin/gdb/gdb/version.c
new file mode 100644
index 000000000000..d32e958a2dd1
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/version.c
@@ -0,0 +1,3 @@
+char *version = "4.11";
+char *host_canonical = "i386-unknown-freebsd";
+char *target_canonical = "i386-unknown-freebsd";
diff --git a/gnu/usr.bin/gdb/gdb/wait.h b/gnu/usr.bin/gdb/gdb/wait.h
new file mode 100644
index 000000000000..a72943cd9ee0
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/wait.h
@@ -0,0 +1,38 @@
+/* Define how to access the int that the wait system call stores.
+ This has been compatible in all Unix systems since time immemorial,
+ but various well-meaning people have defined various different
+ words for the same old bits in the same old int (sometimes claimed
+ to be a struct). We just know it's an int and we use these macros
+ to access the bits. */
+
+/* The following macros are defined equivalently to their definitions
+ in POSIX.1. We fail to define WNOHANG and WUNTRACED, which POSIX.1
+ <sys/wait.h> defines, since our code does not use waitpid(). We
+ also fail to declare wait() and waitpid(). */
+
+#define WIFEXITED(w) (((w)&0377) == 0)
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#ifdef IBM6000
+
+/* Unfortunately, the above comment (about being compatible in all Unix
+ systems) is not quite correct for AIX, sigh. And AIX 3.2 can generate
+ status words like 0x57c (sigtrap received after load), and gdb would
+ choke on it. */
+
+#define WIFSTOPPED(w) ((w)&0x40)
+
+#else
+#define WIFSTOPPED(w) (((w)&0377) == 0177)
+#endif
+
+#define WEXITSTATUS(w) (((w) >> 8) & 0377) /* same as WRETCODE */
+#define WTERMSIG(w) ((w) & 0177)
+#define WSTOPSIG WEXITSTATUS
+
+/* These are not defined in POSIX, but are used by our programs. */
+
+#define WAITTYPE int
+
+#define WCOREDUMP(w) (((w)&0200) != 0)
+#define WSETEXIT(w,status) ((w) = (0 | ((status) << 8)))
+#define WSETSTOP(w,sig) ((w) = (0177 | ((sig) << 8)))
diff --git a/gnu/usr.bin/gdb/gdb/xm.h b/gnu/usr.bin/gdb/gdb/xm.h
new file mode 100644
index 000000000000..8d28df0b713f
--- /dev/null
+++ b/gnu/usr.bin/gdb/gdb/xm.h
@@ -0,0 +1,31 @@
+/* Host-dependent definitions for Intel 386 running BSD Unix, for GDB.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#include <machine/limits.h> /* for INT_MIN, to avoid "INT_MIN
+ redefined" warnings from defs.h */
+
+/* psignal() is in <signal.h>. */
+
+#define PSIGNAL_IN_SIGNAL_H
+
+/* Get rid of any system-imposed stack limit if possible. */
+
+#define SET_STACK_LIMIT_HUGE
diff --git a/gnu/usr.bin/gdb/getpagesize.h b/gnu/usr.bin/gdb/getpagesize.h
deleted file mode 100644
index 32adae61efa2..000000000000
--- a/gnu/usr.bin/gdb/getpagesize.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#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/gnu/usr.bin/gdb/infcmd.c b/gnu/usr.bin/gdb/infcmd.c
deleted file mode 100644
index 378784f22ba6..000000000000
--- a/gnu/usr.bin/gdb/infcmd.c
+++ /dev/null
@@ -1,1204 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)infcmd.c 6.4 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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 "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-#include "inferior.h"
-#include "environ.h"
-#include "value.h"
-
-#include <signal.h>
-#include <sys/param.h>
-
-extern char *sys_siglist[];
-
-#define ERROR_NO_INFERIOR \
- if (inferior_pid == 0) error ("The program is not being run.");
-
-/* String containing arguments to give to the program,
- with a space added at the front. Just a space 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. */
-
-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;
-
-/* Number of breakpoint it stopped at, or 0 if none. */
-
-int stop_breakpoint;
-
-/* 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 ();
-struct command_line *get_breakpoint_commands ();
-void breakpoint_clear_ignore_counts ();
-
-
-int
-have_inferior_p ()
-{
- return inferior_pid != 0;
-}
-
-static void
-set_args_command (args)
- char *args;
-{
- free (inferior_args);
- if (!args) args = "";
- inferior_args = concat (" ", args, "");
-}
-
-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;
-{
- extern char **environ;
- register int i;
- char *exec_file;
- char *allargs;
-
- extern int sys_nerr;
- extern char *sys_errlist[];
- extern int errno;
-
- dont_repeat ();
-
- if (inferior_pid)
- {
- extern int inhibit_confirm;
- if (!(inhibit_confirm ||
- query ("The program being debugged has been started already.\n\
-Start it from the beginning? ")))
- error ("Program not restarted.");
- kill_inferior ();
- }
-
-#if 0
- /* On the other hand, some users want to do
- break open
- ignore 1 40
- run
- So it's not clear what is best. */
-
- /* 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 ();
-#endif
-
- exec_file = (char *) get_exec_file (1);
-
- if (remote_debugging)
- {
- if (from_tty)
- {
- printf ("Starting program: %s\n", exec_file);
- fflush (stdout);
- }
- }
- else
- {
- if (args)
- set_args_command (args);
-
- if (from_tty)
- {
- printf ("Starting program: %s%s\n",
- exec_file, inferior_args);
- fflush (stdout);
- }
-
- allargs = concat ("exec ", exec_file, inferior_args);
- inferior_pid = create_inferior (allargs, environ_vector (inferior_environ));
- }
-
- clear_proceed_status ();
-
- start_inferior ();
-}
-
-void
-cont_command (proc_count_exp, from_tty)
- char *proc_count_exp;
- int from_tty;
-{
- ERROR_NO_INFERIOR;
-
- clear_proceed_status ();
-
- /* If have argument, set proceed count of breakpoint we stopped at. */
-
- if (stop_breakpoint > 0 && proc_count_exp)
- {
- set_ignore_count (stop_breakpoint,
- parse_and_eval_address (proc_count_exp) - 1,
- from_tty);
- if (from_tty)
- printf (" ");
- }
-
- if (from_tty)
- printf ("Continuing.\n");
-
- proceed (-1, -1, 0);
-}
-
-/* Step until outside of current statement. */
-static void step_1 ();
-
-static void
-step_command (count_string)
-{
- step_1 (0, 0, count_string);
-}
-
-/* Likewise, but skip over subroutine calls as if single instructions. */
-
-static void
-next_command (count_string)
-{
- step_1 (1, 0, count_string);
-}
-
-/* Likewise, but step only one instruction. */
-
-static void
-stepi_command (count_string)
-{
- step_1 (0, 1, count_string);
-}
-
-static void
-nexti_command (count_string)
-{
- 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;
-
- ERROR_NO_INFERIOR;
- count = count_string ? parse_and_eval_address (count_string) : 1;
-
- for (; count > 0; count--)
- {
- clear_proceed_status ();
-
- step_frame_address = FRAME_FP (get_current_frame ());
-
- 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);
- 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 (-1, -1, 1);
- if (! stop_step)
- break;
- }
-}
-
-/* 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 = sal.pc;
-
- clear_proceed_status ();
-
- if (from_tty)
- printf ("Continuing at 0x%x.\n", addr);
-
- 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);
-
- clear_proceed_status ();
-
- if (from_tty)
- printf ("Continuing with signal %d.\n", signum);
-
- 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;
- REGISTER_TYPE *buffer;
-{
- /* Now proceed, having reached the desired place. */
- clear_proceed_status ();
-#ifdef notdef
- if (stack_dummy_testing & 4)
- {
- POP_FRAME;
- return;
- }
-#endif
- proceed (addr, 0, 0);
-
- if (!stop_stack_dummy)
- error ("Cannot continue previously requested operation.");
-
- /* On return, the stack dummy has been popped already. */
-
- read_register_bytes(0, buffer, REGISTER_BYTES);
-}
-
-/* Proceed until we reach the given line as argument or exit the
- function. When called with no argument, 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.
-
- The effect of this command with an argument is identical to setting
- a momentary breakpoint at the line specified and executing
- "finish".
-
- 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 (arg, from_tty)
- char *arg;
- 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 (-1, -1, 1);
-}
-
-void
-until_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- if (!have_inferior_p ())
- error ("The program is not being run.");
-
- if (arg)
- until_break_command (arg, from_tty);
- else
- until_next_command (arg, from_tty);
-}
-
-/* "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 (!have_inferior_p ())
- error ("The program is not being run.");
- if (arg)
- error ("The \"finish\" command does not take any arguments.");
-
- 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 (-1, -1, 0);
-
- if (stop_breakpoint == -3 && function != 0)
- {
- struct type *value_type;
- register value val;
- CORE_ADDR funcaddr;
- extern char registers[];
-
- 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, registers,
- using_struct_return (function,
- funcaddr,
- value_type));
-
- printf ("Value returned is $%d = ", record_latest_value (val));
- value_print (val, stdout, 0, Val_no_prettyprint);
- putchar ('\n');
- }
-}
-
-static void
-program_info ()
-{
- if (inferior_pid == 0)
- {
- printf ("The program being debugged is not being run.\n");
- return;
- }
-
- printf ("Program being debugged is in process %d, stopped at 0x%x.\n",
- inferior_pid, stop_pc);
- if (stop_step)
- printf ("It stopped after being stepped.\n");
- else if (stop_breakpoint > 0)
- printf ("It stopped at breakpoint %d.\n", stop_breakpoint);
- else if (stop_signal)
- printf ("It stopped with signal %d (%s).\n",
- stop_signal, sys_siglist[stop_signal]);
-
- printf ("\nType \"info stack\" or \"info reg\" for more information.\n");
-}
-
-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 *) index (arg, '=');
- val = (char *) index (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 ();
- }
-
- unset_in_environ (inferior_environ, var);
-}
-
-/* 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;
- int result_err;
- extern int sys_nerr;
- extern char *sys_errlist[];
-
- if (len == sizeof (char))
- {
- result_err = read_memory (memaddr, &cbuf, len);
- if (result_err)
- error ("Error reading memory address 0x%x: %s (%d).",
- memaddr, (result_err < sys_nerr ?
- sys_errlist[result_err] :
- "uknown error"), result_err);
- return cbuf;
- }
- if (len == sizeof (short))
- {
- result_err = read_memory (memaddr, &sbuf, len);
- if (result_err)
- error ("Error reading memory address 0x%x: %s (%d).",
- memaddr, (result_err < sys_nerr ?
- sys_errlist[result_err] :
- "uknown error"), result_err);
- return sbuf;
- }
- if (len == sizeof (int))
- {
- result_err = read_memory (memaddr, &ibuf, len);
- if (result_err)
- error ("Error reading memory address 0x%x: %s (%d).",
- memaddr, (result_err < sys_nerr ?
- sys_errlist[result_err] :
- "uknown error"), result_err);
- return ibuf;
- }
- if (len == sizeof (lbuf))
- {
- result_err = read_memory (memaddr, &lbuf, len);
- if (result_err)
- error ("Error reading memory address 0x%x: %s (%d).",
- memaddr, (result_err < sys_nerr ?
- sys_errlist[result_err] :
- "uknown error"), result_err);
- return lbuf;
- }
- error ("Cannot handle integers of %d bytes.", len);
-}
-
-CORE_ADDR
-read_pc ()
-{
- return (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
-}
-
-char *reg_names[] = REGISTER_NAMES;
-
-#if !defined (DO_REGISTERS_INFO)
-static void
-print_one_register(i)
- int i;
-{
- unsigned char raw_buffer[MAX_REGISTER_RAW_SIZE];
- unsigned char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
- REGISTER_TYPE val;
-
- /* Get the data in raw format, then convert also to virtual format. */
- read_relative_register_raw_bytes (i, raw_buffer);
- REGISTER_CONVERT_TO_VIRTUAL (i, raw_buffer, virtual_buffer);
-
- fputs_filtered (reg_names[i], stdout);
- print_spaces_filtered (15 - strlen (reg_names[i]), stdout);
-
- /* If virtual format is floating, print it that way. */
- if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT
- && ! INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
- val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0,
- stdout, 0, 1, 0, Val_pretty_default);
- /* 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", virtual_buffer[j]);
- }
- /* Else print as integer in hex and in decimal. */
- else
- {
- long val;
-
- bcopy (virtual_buffer, &val, sizeof (long));
- if (val == 0)
- printf_filtered ("0");
- else
- printf_filtered ("0x%08x %d", val, val);
- }
-
- /* If register has different raw and virtual formats,
- print the raw format in hex now. */
-
- if (REGISTER_CONVERTIBLE (i))
- {
- register int j;
-
- printf_filtered (" (raw 0x");
- for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
- printf_filtered ("%02x", raw_buffer[j]);
- printf_filtered (")");
- }
- printf_filtered ("\n");
-}
-
-
-/* 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. */
-static void
-do_registers_info (regnum, fpregs)
- int regnum;
- int fpregs;
-{
- register int i;
-
- if (regnum >= 0) {
- print_one_register(regnum);
- return;
- }
-#ifdef notdef
- printf_filtered (
-"Register Contents (relative to selected stack frame)\n\n");
-#endif
- for (i = 0; i < NUM_REGS; i++)
- if (TYPE_CODE(REGISTER_VIRTUAL_TYPE(i)) != TYPE_CODE_FLT ||
- fpregs)
- print_one_register(i);
-}
-#endif /* no DO_REGISTERS_INFO. */
-
-static void
-registers_info (addr_exp, fpregs)
- char *addr_exp;
- int fpregs;
-{
- int regnum;
-
- if (!have_inferior_p () && !have_core_file_p ())
- error ("No inferior or core file");
-
- 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;
-
-#ifdef DO_REGISTERS_INFO
- DO_REGISTERS_INFO(regnum);
-#else
- do_registers_info(regnum, fpregs);
-#endif
-}
-
-static void
-all_registers_info (addr_exp)
- char *addr_exp;
-{
- registers_info(addr_exp, 1);
-}
-
-static void
-nofp_registers_info (addr_exp)
- char *addr_exp;
-{
- registers_info(addr_exp, 0);
-}
-
-
-#ifdef ATTACH_DETACH
-#define PROCESS_ATTACH_ALLOWED 1
-#else
-#define PROCESS_ATTACH_ALLOWED 0
-#endif
-/*
- * 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.
- */
-static void
-attach_command (args, from_tty)
- char *args;
- int from_tty;
-{
- char *exec_file;
- int pid;
- int remote = 0;
-
- dont_repeat();
-
- if (!args)
- error_no_arg ("process-id or device file to attach");
-
- while (*args == ' ' || *args == '\t') args++;
-
- if (args[0] < '0' || args[0] > '9')
- remote = 1;
- else
-#ifndef ATTACH_DETACH
- error ("Can't attach to a process on this machine.");
-#else
- pid = atoi (args);
-#endif
-
- if (inferior_pid)
- {
- if (query ("A program is being debugged already. Kill it? "))
- kill_inferior ();
- else
- error ("Inferior not killed.");
- }
-
- exec_file = (char *) get_exec_file (1);
-
- if (from_tty)
- {
- if (remote)
- printf ("Attaching remote machine\n");
- else
- printf ("Attaching program: %s pid %d\n",
- exec_file, pid);
- fflush (stdout);
- }
-
- if (remote)
- {
- remote_open (args, from_tty);
- start_remote ();
- }
-#ifdef ATTACH_DETACH
- else
- attach_program (pid);
-#endif
-}
-
-/*
- * 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;
-{
- int signal = 0;
-
-#ifdef ATTACH_DETACH
- if (inferior_pid && !remote_debugging)
- {
- if (from_tty)
- {
- char *exec_file = (char *)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)
- signal = atoi (args);
-
- detach (signal);
- inferior_pid = 0;
- }
- else
-#endif
- {
- if (!remote_debugging)
- error ("Not currently attached to subsidiary or remote process.");
-
- if (args)
- error ("Argument given to \"detach\" when remotely debugging.");
-
- inferior_pid = 0;
- remote_close (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
-}
-
-extern struct cmd_list_element *setlist, *deletelist;
-
-void
-_initialize_infcmd ()
-{
- add_com ("tty", class_run, tty_command,
- "Set terminal for future runs of program being debugged.");
-
- add_cmd ("args", class_run, set_args_command,
- "Specify 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);
-
- add_info ("environment", 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.");
-
- 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);
-
- 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);
-
-#ifdef ATTACH_DETACH
- add_com ("attach", class_run, attach_command,
- "Attach to a process that was started up outside of GDB.\n\
-This 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\
-For a device file, the file must be a connection to a remote debug server.\n\n\
-Before using \"attach\", you must use the \"exec-file\" command\n\
-to specify the program running in the process,\n\
-and the \"symbol-file\" command to load its symbol table.");
-#else
- add_com ("attach", class_run, attach_command,
- "Attach to a process that was started up outside of GDB.\n\
-This commands takes as an argument the name of a device file.\n\
-This file must be a connection to a remote debug server.\n\n\
-Before using \"attach\", you must use the \"exec-file\" command\n\
-to specify the program running in the process,\n\
-and the \"symbol-file\" command to load its symbol table.");
-#endif
- add_com ("detach", class_run, detach_command,
- "Detach the process previously attached.\n\
-The process is no longer traced and continues its execution.");
-
- 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 ("cont", class_run, cont_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 ("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", nofp_registers_info,
- "List of registers and their contents, for selected stack frame.\n\
-Register name as argument means describe only that register.\n\
-(Doesn't display floating point registers; use 'info all-registers'.)\n");
-
- add_info ("all-registers", all_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); /* By default, no args. */
- inferior_environ = make_environ ();
- init_environ (inferior_environ);
-}
-
diff --git a/gnu/usr.bin/gdb/inferior.h b/gnu/usr.bin/gdb/inferior.h
deleted file mode 100644
index 04c662e4626c..000000000000
--- a/gnu/usr.bin/gdb/inferior.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * @(#)inferior.h 6.3 (Berkeley) 5/8/91
- */
-
-/* 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. */
-
-/*
- * 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;
- int stop_frame_address;
- int stop_breakpoint;
- 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_after_attach;
- FRAME_ADDR selected_frame_address;
- int selected_level;
- struct command_line *breakpoint_commands;
- char register_context[REGISTER_BYTES];
- int restore_stack_info;
-};
-
-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;
-
-/* Nonzero if debugging a remote machine via a serial link or ethernet. */
-extern int remote_debugging;
-
-/* Routines for use in remote debugging. Documented in remote.c. */
-int remote_read_inferior_memory ();
-int remote_write_inferior_memory ();
-
-/* 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;
-
-/* Number of breakpoint it stopped at, or 0 if none. */
-
-extern int stop_breakpoint;
-
-/* 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;
-
-/* Save register contents here when about to pop a stack dummy frame. */
-
-extern char stop_registers[REGISTER_BYTES];
-
-/* Nonzero if pc has been changed by the debugger
- since the inferior stopped. */
-
-extern int pc_changed;
-
-long read_memory_integer ();
diff --git a/gnu/usr.bin/gdb/inflow.c b/gnu/usr.bin/gdb/inflow.c
deleted file mode 100644
index 209fcf373458..000000000000
--- a/gnu/usr.bin/gdb/inflow.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)inflow.c 6.5 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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. */
-
-#include <stdio.h>
-#include "defs.h"
-#include "param.h"
-#include "frame.h"
-#include "inferior.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>
-
-#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
-#else
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <sgtty.h>
-#define TERMINAL struct sgttyb
-#endif
-
-#ifdef SET_STACK_LIMIT_HUGE
-#include <sys/time.h>
-#include <sys/resource.h>
-extern int original_stack_limit;
-#endif /* SET_STACK_LIMIT_HUGE */
-
-extern int errno;
-
-/* Nonzero if we are debugging an attached outside process
- rather than an inferior. */
-
-int attach_flag;
-
-
-/* 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 int (*sigint_ours) ();
-static int (*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 ()
-{
- if (remote_debugging)
- return;
-
- 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 (remote_debugging)
- return;
-
- 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 = (int (*) ()) signal (SIGINT, SIG_IGN);
- sigquit_ours = (int (*) ()) 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 ()
-{
- if (remote_debugging)
- return;
-
- 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 ()
-{
- if (remote_debugging)
- return;
-
- 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 */
-
- if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
- {
- terminal_is_ours = 1;
-
-#ifdef TIOCGPGRP
- osigttou = 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 */
-}
-
-static void
-term_status_command ()
-{
- register int i;
-
- if (remote_debugging)
- {
- printf_filtered ("No terminal status when remote debugging.\n");
- return;
- }
-
- 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 < 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 < sizeof (struct ltchars); i++)
- printf_filtered ("0x%x ", ((char *)&ltc_inferior)[i]);
- printf_filtered ("\n");
- ioctl (0, TIOCSLTC, &ltc_ours);
-#endif
-
-#ifdef TIOCLGET
- printf_filtered ("lmode: %x\n", lmode_inferior);
-#endif
-}
-
-static void
-new_tty (ttyname)
- char *ttyname;
-{
- register int tty;
- register int fd;
-
-#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)
- _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);
-}
-
-/* Start an inferior process and returns its pid.
- ALLARGS is a string containing shell command to run the program.
- ENV is the environment vector to pass. */
-
-#ifndef SHELL_FILE
-#define SHELL_FILE "/bin/sh"
-#endif
-
-int
-create_inferior (allargs, env)
- char *allargs;
- char **env;
-{
- int pid;
- char *shell_command;
- extern int sys_nerr;
- extern char *sys_errlist[];
- extern int errno;
-
- /* 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) + strlen (allargs) + 1);
- strcpy (shell_command, SHELL_COMMAND_CONCAT);
- strcat (shell_command, allargs);
-#else
- shell_command = allargs;
-#endif
-
- /* exec is said to fail if the executable is open. */
- close_exec_file ();
-
-#if defined(USG) && !defined(HAVE_VFORK)
- pid = fork ();
-#else
- pid = vfork ();
-#endif
-
- if (pid < 0)
- perror_with_name ("vfork");
-
- if (pid == 0)
- {
-#ifdef TIOCGPGRP
- /* Run inferior in a separate process group. */
- setpgrp (getpid (), getpid ());
-#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 */
-
-
- inferior_thisrun_terminal = inferior_io_terminal;
- if (inferior_io_terminal != 0)
- new_tty (inferior_io_terminal);
-
-/* It seems that changing the signal handlers for the inferior after
- a vfork also changes them for the superior. See comments in
- initialize_signals for how we get the right signal handlers
- for the inferior. */
-/* Not needed on Sun, at least, and loses there
- because it clobbers the superior. */
-/*??? signal (SIGQUIT, SIG_DFL);
- signal (SIGINT, SIG_DFL); */
-
- call_ptrace (0);
- execle (SHELL_FILE, "sh", "-c", shell_command, 0, env);
-
- fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE,
- errno < sys_nerr ? sys_errlist[errno] : "unknown error");
- fflush (stderr);
- _exit (0177);
- }
-
-#ifdef TIOCGPGRP
- /* Avoid race with TIOCSPGRP: guarantee that inferior's pgrp exists. */
- setpgrp (pid, pid);
-#endif /* TIOCGPGRP */
-
-#ifdef CREATE_INFERIOR_HOOK
- CREATE_INFERIOR_HOOK (pid);
-#endif
- return pid;
-}
-
-/* Kill the inferior process. Make us have no inferior. */
-
-static void
-kill_command ()
-{
- if (remote_debugging)
- {
- inferior_pid = 0;
- return;
- }
- if (inferior_pid == 0)
- error ("The program is not being run.");
- if (!query ("Kill the inferior process? "))
- error ("Not confirmed.");
- kill_inferior ();
-}
-
-void
-inferior_died ()
-{
- inferior_pid = 0;
- attach_flag = 0;
- mark_breakpoints_out ();
- select_frame ((FRAME) 0, -1);
- reopen_exec_file ();
- if (have_core_file_p ())
- set_current_frame ( create_new_frame (read_register (FP_REGNUM),
- read_pc ()));
- else
- set_current_frame (0);
-}
-
-#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). */
-static 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.");
-
- /* 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
-
-void
-_initialize_inflow ()
-{
- add_com ("term-status", class_obscure, term_status_command,
- "Print info on 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);
- tflags_ours = fcntl (0, F_GETFL, 0);
-
-#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/gnu/usr.bin/gdb/infrun.c b/gnu/usr.bin/gdb/infrun.c
deleted file mode 100644
index 887a0bb4e4cd..000000000000
--- a/gnu/usr.bin/gdb/infrun.c
+++ /dev/null
@@ -1,1459 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)infrun.c 6.4 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* Start and stop the 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. */
-
-/* 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.
- randy@wheaties.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 "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-#include "inferior.h"
-#include "wait.h"
-
-#include <signal.h>
-
-/* unistd.h is needed to #define X_OK */
-#ifdef USG
-#include <unistd.h>
-#else
-#include <sys/file.h>
-#endif
-
-#ifdef UMAX_PTRACE
-#include <aouthdr.h>
-#include <sys/param.h>
-#include <sys/ptrace.h>
-#endif /* UMAX_PTRACE */
-
-/* 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 *sys_siglist[];
-extern int errno;
-
-/* 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. */
-
-static int breakpoints_inserted;
-
-/* Function inferior was in as of last step command. */
-
-static struct symbol *step_start_function;
-
-/* This is the sequence of bytes we insert for a breakpoint. */
-
-static char break_insn[] = BREAKPOINT;
-
-/* Nonzero => address for special breakpoint for resuming stepping. */
-
-static CORE_ADDR step_resume_break_address;
-
-/* Original contents of the byte where the special breakpoint is. */
-
-static char step_resume_break_shadow[sizeof break_insn];
-
-/* 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.
- 2 means expecting 2 trace traps and should continue both times.
- That occurs when we tell sh to exec the program: we will get
- a trap after the exec of sh and a second when the program is exec'd. */
-
-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 trace trap due to attaching to a process. */
-
-int stop_after_attach;
-
-/* Nonzero if pc has been changed by the debugger
- since the inferior stopped. */
-
-int pc_changed;
-
-/* Nonzero if debugging a remote machine via a serial link or ethernet. */
-
-int remote_debugging;
-
-/* Nonzero if program stopped due to error trying to insert breakpoints. */
-
-static int breakpoints_failed;
-
-/* Nonzero if inferior is in sh before our program got exec'd. */
-
-static int running_in_shell;
-
-/* 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 ();
-static void normal_stop ();
-
-
-/* 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_after_attach = 0;
-
- /* Discard any remaining commands left by breakpoint we had stopped at. */
- clear_breakpoint_commands ();
-}
-
-/* Basic routine for continuing the program in various fashions.
-
- ADDR is the address to resume at, or -1 for resume where stopped.
- SIGNAL 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, signal, step)
- CORE_ADDR addr;
- int signal;
- 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);
-#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. */
- terminal_inferior ();
-
- if (signal >= 0)
- stop_signal = signal;
- /* 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;
-
- /* Resume inferior. */
- resume (oneproc || 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 ();
-}
-
-/* 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;
-}
-
-/* Start an inferior process for the first time.
- Actually it was started by the fork that created it,
- but it will have stopped one instruction after execing sh.
- Here we must get it up to actual execution of the real program. */
-
-void
-start_inferior ()
-{
- /* 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
- trap_expected = START_INFERIOR_TRAPS_EXPECTED;
-#else
- trap_expected = 2;
-#endif
-
- running_in_shell = 0; /* Set to 1 at first SIGTRAP, 0 at second. */
- trap_expected_after_continue = 0;
- breakpoints_inserted = 0;
- mark_breakpoints_out ();
-
- /* Set up the "saved terminal modes" of the inferior
- based on what modes we are starting it with. */
- terminal_init_inferior ();
-
- /* Install inferior's terminal modes. */
- terminal_inferior ();
-
- if (remote_debugging)
- {
- trap_expected = 0;
- fetch_inferior_registers();
- set_current_frame (create_new_frame (read_register (FP_REGNUM),
- read_pc ()));
- stop_frame_address = FRAME_FP (get_current_frame());
- inferior_pid = 3;
- if (insert_breakpoints())
- fatal("Can't insert breakpoints");
- breakpoints_inserted = 1;
- proceed(-1, -1, 0);
- }
- else
- {
- wait_for_inferior ();
- normal_stop ();
- }
-}
-
-/* Start or restart remote-debugging of a machine over a serial link. */
-
-void
-restart_remote ()
-{
- clear_proceed_status ();
- running_in_shell = 0;
- trap_expected = 0;
- stop_after_attach = 1;
- inferior_pid = 3;
- wait_for_inferior ();
- normal_stop();
-}
-
-void
-start_remote ()
-{
- breakpoints_inserted = 0;
- mark_breakpoints_out ();
- restart_remote();
-}
-
-#ifdef ATTACH_DETACH
-
-/* Attach to process PID, then initialize for debugging it
- and wait for the trace-trap that results from attaching. */
-
-void
-attach_program (pid)
- int pid;
-{
- attach (pid);
- inferior_pid = pid;
-
- mark_breakpoints_out ();
- terminal_init_inferior ();
- clear_proceed_status ();
- stop_after_attach = 1;
- /*proceed (-1, 0, -2);*/
- terminal_inferior ();
- wait_for_inferior ();
- normal_stop ();
-}
-#endif /* ATTACH_DETACH */
-
-/* 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. */
-
-static void
-wait_for_inferior ()
-{
- register int pid;
- WAITTYPE w;
- CORE_ADDR pc;
- int tem;
- int another_trap;
- int random_signal;
- CORE_ADDR stop_sp, prev_sp;
- CORE_ADDR prev_func_start, stop_func_start;
- char *prev_func_name, *stop_func_name;
- CORE_ADDR prologue_pc;
- int stop_step_resume_break;
- CORE_ADDR step_resume_break_sp;
- int newmisc;
- int newfun_pc;
- struct symtab_and_line sal;
- int prev_pc;
- extern CORE_ADDR text_end;
- int remove_breakpoints_on_following_step = 0;
-
- 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);
-
- while (1)
- {
- /* Clean up saved state that will become invalid. */
- pc_changed = 0;
- flush_cached_frames ();
-
- if (remote_debugging)
- remote_wait (&w);
- else
- {
- pid = wait (&w);
- if (pid != inferior_pid)
- continue;
- }
-
- /* See if the process still exists; clean up if it doesn't. */
- if (WIFEXITED (w))
- {
- terminal_ours_for_output ();
- if (WEXITSTATUS (w))
- printf ("\nProgram exited with code 0%o.\n", WEXITSTATUS (w));
- else
- printf ("\nProgram exited normally.\n");
- fflush (stdout);
- inferior_died ();
-#ifdef NO_SINGLE_STEP
- one_stepped = 0;
-#endif
- stop_print_frame = 0;
- break;
- }
- else if (!WIFSTOPPED (w))
- {
- kill_inferior ();
- stop_print_frame = 0;
- stop_signal = WTERMSIG (w);
- terminal_ours_for_output ();
- printf ("\nProgram terminated with signal %d, %s\n",
- stop_signal,
- stop_signal < NSIG
- ? sys_siglist[stop_signal]
- : "(undocumented)");
- 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 */
-
- fetch_inferior_registers ();
- 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;
- stop_breakpoint = 0;
- 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_after_attach)
- {
- if (stop_signal == SIGTRAP && stop_after_trap)
- {
- stop_print_frame = 0;
- break;
- }
- if (stop_after_attach)
- break;
- /* Don't even think about breakpoints
- if still running the shell that will exec the program
- or if just proceeded over a breakpoint. */
- if (stop_signal == SIGTRAP && trap_expected)
- stop_breakpoint = 0;
- 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 (stop_pc - DECR_PC_AFTER_BREAK
- == 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_breakpoint =
- breakpoint_stop_status (stop_pc, stop_frame_address);
- /* Following in case break condition called a
- function. */
- stop_print_frame = 1;
- if (stop_breakpoint && DECR_PC_AFTER_BREAK)
- {
- stop_pc -= DECR_PC_AFTER_BREAK;
- write_register (PC_REGNUM, stop_pc);
-#ifdef NPC_REGNUM
- write_register (NPC_REGNUM, stop_pc + 4);
-#endif
- pc_changed = 0;
- }
- }
- }
- }
-
- if (stop_signal == SIGTRAP)
- random_signal
- = !(stop_breakpoint || trap_expected
- || stop_step_resume_break
-#ifndef CANNOT_EXECUTE_STACK
- || (stop_sp INNER_THAN stop_pc
- && stop_pc INNER_THAN stop_frame_address)
-#else
- || stop_pc == text_end - 2
-#endif
- || (step_range_end && !step_resume_break_address));
- else
- {
- random_signal
- = !(stop_breakpoint
- || stop_step_resume_break
-#ifdef sony_news
- || (stop_sp INNER_THAN stop_pc
- && stop_pc INNER_THAN stop_frame_address)
-#endif
-
- );
- 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
- && !(running_in_shell && stop_signal == SIGSEGV))
- {
- /* Signal not for debugging purposes. */
- int printed = 0;
-
- stopped_by_random_signal = 1;
-
- if (stop_signal >= NSIG
- || signal_print[stop_signal])
- {
- printed = 1;
- terminal_ours_for_output ();
- printf ("\nProgram received signal %d, %s\n",
- stop_signal,
- stop_signal < NSIG
- ? sys_siglist[stop_signal]
- : "(undocumented)");
- 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)
- terminal_inferior ();
- }
-
- /* Handle cases caused by hitting a breakpoint. */
-
- if (!random_signal
- && (stop_breakpoint || stop_step_resume_break))
- {
- /* Does a breakpoint want us to stop? */
- if (stop_breakpoint && stop_breakpoint != -1
- && stop_breakpoint != -0x1000001)
- {
- /* 0x1000000 is set in stop_breakpoint as returned by
- breakpoint_stop_status to indicate a silent
- breakpoint. */
- if ((stop_breakpoint > 0 ? stop_breakpoint :
- -stop_breakpoint)
- & 0x1000000)
- {
- stop_print_frame = 0;
- if (stop_breakpoint > 0)
- stop_breakpoint -= 0x1000000;
- else
- stop_breakpoint += 0x1000000;
- }
- 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;
- }
- /* 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. */
-#ifndef CANNOT_EXECUTE_STACK
- if (stop_sp INNER_THAN stop_pc
- && stop_pc INNER_THAN stop_frame_address)
-#else
- if (stop_pc == text_end - 2)
-#endif
- {
- 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)))
- {
- /* 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;
- }
- }
-
- /* 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);
- step_resume_break_sp = stop_sp;
- 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 =
- SAVED_PC_AFTER_CALL (get_current_frame ());
- step_resume_break_duplicate
- = breakpoint_here_p (step_resume_break_address);
- step_resume_break_sp = stop_sp;
- 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_sp = stop_sp;
-
- 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;
- }
- }
-
- /* 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 is 2, it means continue once more
- and insert breakpoints at the next trap.
- If trap_expected is 1 and the signal was SIGSEGV, it means
- the shell is doing some memory allocation--just resume it
- with SIGSEGV.
- Otherwise insert breakpoints now, and possibly single step. */
-
- if (trap_expected > 1)
- {
- trap_expected--;
- running_in_shell = 1;
- resume (0, 0);
- }
- else if (running_in_shell && stop_signal == SIGSEGV)
- {
- resume (0, SIGSEGV);
- }
- else if (trap_expected && stop_signal != SIGTRAP)
- {
- /* We took a signal which we are supposed to pass through to
- the inferior and we haven't yet gotten our trap. Simply
- continue. */
- resume ((step_range_end && !step_resume_break_address)
- || trap_expected,
- stop_signal);
- }
- else
- {
- /* Here, we are not awaiting another exec to get
- the program we really want to debug.
- Insert breakpoints now, unless we are trying
- to one-proceed past a breakpoint. */
- running_in_shell = 0;
- /* 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 && !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;
-
- resume ((step_range_end && !step_resume_break_address)
- || trap_expected,
- stop_signal);
- }
- }
-}
-
-/* Here to return control to GDB when the inferior stops for real.
- Print appropriate messages, remove breakpoints, give terminal our modes.
-
- RUNNING_IN_SHELL nonzero means the shell got a signal before
- exec'ing the program we wanted to run.
- 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. */
-
-static 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 (inferior_pid)
- (get_current_frame ())->pc = read_pc ();
-
- if (breakpoints_failed)
- {
- 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 (inferior_pid)
- remove_step_breakpoint ();
-
- if (inferior_pid && breakpoints_inserted)
- if (remove_breakpoints ())
- {
- terminal_ours_for_output ();
- printf ("Cannot remove breakpoints because program is no longer writable.\n\
-It must 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_breakpoint);
-
- /* 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;
-
- terminal_ours ();
-
- if (running_in_shell)
- {
- if (stop_signal == SIGSEGV)
- {
- char *exec_file = (char *) get_exec_file (1);
-
- if (access (exec_file, X_OK) != 0)
- printf ("The file \"%s\" is not executable.\n", exec_file);
- else
- /* I don't think we should ever get here.
- wait_for_inferior now ignores SIGSEGV's which happen in
- the shell (since the Bourne shell (/bin/sh) has some
- rather, er, uh, *unorthodox* memory management
- involving catching SIGSEGV). */
- printf ("\
-You have just encountered a bug in \"sh\". GDB starts your program\n\
-by running \"sh\" with a command to exec your program.\n\
-This is so that \"sh\" will process wildcards and I/O redirection.\n\
-This time, \"sh\" crashed.\n\
-\n\
-One known bug in \"sh\" bites when the environment takes up a lot of space.\n\
-Try \"info env\" to see the environment; then use \"delete env\" to kill\n\
-some variables whose values are large; then do \"run\" again.\n\
-\n\
-If that works, you might want to put those \"delete env\" commands\n\
-into a \".gdbinit\" file in this directory so they will happen every time.\n");
- }
- /* Don't confuse user with his program's symbols on sh's data. */
- stop_print_frame = 0;
- }
-
- if (inferior_pid == 0)
- 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)
- {
- if (stop_breakpoint > 0)
- printf ("\nBpt %d, ", stop_breakpoint);
- print_sel_frame (stop_step
- && step_frame_address == stop_frame_address
- && step_start_function == find_pc_function (stop_pc));
- /* Display the auto-display expressions. */
- do_displays ();
- }
- }
-
- 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. */
-#ifndef NEW_CALL_FUNCTION
- POP_FRAME;
-#endif
- select_frame (get_current_frame (), 0);
- }
-}
-
-static void
-insert_step_breakpoint ()
-{
- if (step_resume_break_address && !step_resume_break_duplicate)
- {
- read_memory (step_resume_break_address,
- step_resume_break_shadow, sizeof break_insn);
- write_memory (step_resume_break_address,
- break_insn, sizeof break_insn);
- }
-}
-
-static void
-remove_step_breakpoint ()
-{
- if (step_resume_break_address && !step_resume_break_duplicate)
- write_memory (step_resume_break_address, step_resume_break_shadow,
- sizeof break_insn);
-}
-
-/* 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;
-
- 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++);
- for (digits = 0; p[digits] >= '0' && p[digits] <= '9'; digits++);
-
- /* If it is all digits, it is signal number to operate on. */
- if (digits == wordlen)
- {
- signum = atoi (p);
- if (signum <= 0 || signum >= NSIG)
- {
- p[wordlen] = '\0';
- error ("Invalid signal %s given as argument to \"handle\".", p);
- }
- if (signum == SIGTRAP || signum == SIGINT)
- {
- if (!query ("Signal %d is used by the debugger.\nAre you sure you want to change it? ", signum))
- error ("Not confirmed.");
- }
- }
- else if (signum == 0)
- error ("First argument is not a signal number.");
-
- /* 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
- {
- p[wordlen] = 0;
- error ("Unrecognized flag word: \"%s\".", p);
- }
-
- /* Find start of next word. */
- p += wordlen;
- while (*p == ' ' || *p == '\t') p++;
- }
-
- if (from_tty)
- {
- /* Show the results. */
- printf ("Number\tStop\tPrint\tPass to program\tDescription\n");
- printf ("%d\t", signum);
- printf ("%s\t", signal_stop[signum] ? "Yes" : "No");
- printf ("%s\t", signal_print[signum] ? "Yes" : "No");
- printf ("%s\t\t", signal_program[signum] ? "Yes" : "No");
- printf ("%s\n", sys_siglist[signum]);
- }
-}
-
-/* Print current contents of the tables set by the handle command. */
-
-static void
-signals_info (signum_exp)
- char *signum_exp;
-{
- register int i;
- printf_filtered ("Number\tStop\tPrint\tPass to program\tDescription\n");
-
- if (signum_exp)
- {
- i = parse_and_eval_address (signum_exp);
- if (i >= NSIG || i < 0)
- error ("Signal number out of bounds.");
- printf_filtered ("%d\t", i);
- printf_filtered ("%s\t", signal_stop[i] ? "Yes" : "No");
- printf_filtered ("%s\t", signal_print[i] ? "Yes" : "No");
- printf_filtered ("%s\t\t", signal_program[i] ? "Yes" : "No");
- printf_filtered ("%s\n", sys_siglist[i]);
- return;
- }
-
- printf_filtered ("\n");
- for (i = 0; i < NSIG; i++)
- {
- QUIT;
-
- printf_filtered ("%d\t", i);
- printf_filtered ("%s\t", signal_stop[i] ? "Yes" : "No");
- printf_filtered ("%s\t", signal_print[i] ? "Yes" : "No");
- printf_filtered ("%s\t\t", signal_program[i] ? "Yes" : "No");
- printf_filtered ("%s\n", sys_siglist[i]);
- }
-
- printf_filtered ("\nUse the \"handle\" command to change these tables.\n");
-}
-
-/* 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). */
-
-struct command_line *get_breakpoint_commands ();
-
-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_breakpoint = stop_breakpoint;
- 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_after_attach = stop_after_attach;
- inf_status->breakpoint_commands = get_breakpoint_commands ();
- inf_status->restore_stack_info = restore_stack_info;
-
- read_register_bytes(0, inf_status->register_context, 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_breakpoint = inf_status->stop_breakpoint;
- 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_after_attach = inf_status->stop_after_attach;
- set_breakpoint_commands (inf_status->breakpoint_commands);
-
- write_register_bytes(0, inf_status->register_context, REGISTER_BYTES);
-
- /* The inferior can be gone if the user types "print exit(0)"
- (and perhaps other times). */
- if (have_inferior_p() && inf_status->restore_stack_info)
- {
- flush_cached_frames();
- set_current_frame(create_new_frame(read_register (FP_REGNUM),
- read_pc()));
-
- fid = find_relative_frame (get_current_frame (), &level);
-
- if (fid == 0 ||
- FRAME_FP (fid) != inf_status->selected_frame_address ||
- level != 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");
- select_frame (get_current_frame (), 0);
- return;
- }
-
- select_frame (fid, inf_status->selected_level);
- }
- return;
-}
-
-
-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/gnu/usr.bin/gdb/kgdb_proto.h b/gnu/usr.bin/gdb/kgdb_proto.h
deleted file mode 100644
index 9da8d2b4eba3..000000000000
--- a/gnu/usr.bin/gdb/kgdb_proto.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*-
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Steven McCanne of Lawrence Berkeley Laboratory.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)kgdb_proto.h 6.3 (Berkeley) 5/8/91
- *
- *
- * $Header: /home/cvs/386BSD/src/gnu/usr.bin/gdb/kgdb_proto.h,v 1.1 1993/06/29 09:47:25 nate Exp $ (LBL)
- */
-
-/*
- * Message types.
- */
-#define KGDB_MEM_R 0x01
-#define KGDB_MEM_W 0x02
-#define KGDB_REG_R 0x03
-#define KGDB_REG_W 0x04
-#define KGDB_CONT 0x05
-#define KGDB_STEP 0x06
-#define KGDB_KILL 0x07
-#define KGDB_SIGNAL 0x08
-#define KGDB_EXEC 0x09
-
-#define KGDB_CMD(x) ((x) & 0x0f)
-
-/*
- * Message flags.
- */
-#define KGDB_ACK 0x80
-#define KGDB_DELTA 0x40
-#define KGDB_MORE 0x20
-#define KGDB_SEQ 0x10
diff --git a/gnu/usr.bin/gdb/libiberty/COPYING.LIB b/gnu/usr.bin/gdb/libiberty/COPYING.LIB
new file mode 100644
index 000000000000..eb685a5ec981
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 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.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), 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 library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ 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.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library 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 Library
+specifies a version number of this 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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; 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.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/gnu/usr.bin/gdb/libiberty/Makefile b/gnu/usr.bin/gdb/libiberty/Makefile
new file mode 100644
index 000000000000..838781295e82
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/Makefile
@@ -0,0 +1,13 @@
+LIB= iberty
+SRCS= argv.c basename.c concat.c cplus-dem.c fdmatch.c getopt.c \
+ getopt1.c ieee-float.c obstack.c spaces.c strerror.c strsignal.c \
+ xmalloc.c
+
+CFLAGS+= -I$(.CURDIR)/../gdb/.
+NOPROFILE=no
+NOPIC=no
+
+install:
+ @echo -n
+
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/gdb/libiberty/README.FreeBSD b/gnu/usr.bin/gdb/libiberty/README.FreeBSD
new file mode 100644
index 000000000000..573fa0a9a809
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/README.FreeBSD
@@ -0,0 +1,7 @@
+This is a greatly pared down libiberty directory. Only what's required to build
+gdb-4.12 on FreeBSD was kept.
+
+This is temporary. In FreeBSD 2.0 a fully ported libiberty will likely appear
+as a system library for use by all the build tools.
+
+paul@freefall.cdrom.com
diff --git a/gnu/usr.bin/gdb/libiberty/alloca-conf.h b/gnu/usr.bin/gdb/libiberty/alloca-conf.h
new file mode 100644
index 000000000000..e1d9177893a1
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/alloca-conf.h
@@ -0,0 +1,11 @@
+/* "Normal" configuration for alloca. */
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#ifdef sparc
+#include <alloca.h>
+#else
+char *alloca ();
+#endif /* sparc */
+#endif /* not __GNUC__ */
diff --git a/gnu/usr.bin/gdb/libiberty/argv.c b/gnu/usr.bin/gdb/libiberty/argv.c
new file mode 100644
index 000000000000..fed46e7d797b
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/argv.c
@@ -0,0 +1,332 @@
+/* Create and destroy argument vectors (argv's)
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by Fred Fish @ Cygnus Support
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+
+/* Create and destroy argument vectors. An argument vector is simply an
+ array of string pointers, terminated by a NULL pointer. */
+
+/* AIX requires this to be the first thing in the file. */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#ifdef sparc
+#include <alloca.h>
+extern char *__builtin_alloca(); /* Stupid include file doesn't declare it */
+#else
+#ifdef _AIX
+ #pragma alloca
+#else
+char *alloca ();
+#endif
+#endif /* sparc */
+#endif /* not __GNUC__ */
+
+#define isspace(ch) ((ch) == ' ' || (ch) == '\t')
+
+#include "alloca-conf.h"
+
+/* Routines imported from standard C runtime libraries. */
+
+#ifdef __STDC__
+
+#include <stddef.h>
+extern void *memcpy (void *s1, const void *s2, size_t n); /* 4.11.2.1 */
+extern size_t strlen (const char *s); /* 4.11.6.3 */
+extern void *malloc (size_t size); /* 4.10.3.3 */
+extern void *realloc (void *ptr, size_t size); /* 4.10.3.4 */
+extern void free (void *ptr); /* 4.10.3.2 */
+extern char *strdup (const char *s); /* Non-ANSI */
+
+#else /* !__STDC__ */
+
+extern char *memcpy (); /* Copy memory region */
+extern int strlen (); /* Count length of string */
+extern char *malloc (); /* Standard memory allocater */
+extern char *realloc (); /* Standard memory reallocator */
+extern void free (); /* Free malloc'd memory */
+extern char *strdup (); /* Duplicate a string */
+
+#endif /* __STDC__ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef EOS
+#define EOS '\0'
+#endif
+
+#define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */
+
+
+/*
+
+NAME
+
+ freeargv -- free an argument vector
+
+SYNOPSIS
+
+ void freeargv (vector)
+ char **vector;
+
+DESCRIPTION
+
+ Free an argument vector that was built using buildargv. Simply scans
+ through the vector, freeing the memory for each argument until the
+ terminating NULL is found, and then frees the vector itself.
+
+RETURNS
+
+ No value.
+
+*/
+
+void freeargv (vector)
+char **vector;
+{
+ register char **scan;
+
+ if (vector != NULL)
+ {
+ for (scan = vector; *scan != NULL; scan++)
+ {
+ free (*scan);
+ }
+ free (vector);
+ }
+}
+
+/*
+
+NAME
+
+ buildargv -- build an argument vector from a string
+
+SYNOPSIS
+
+ char **buildargv (sp)
+ char *sp;
+
+DESCRIPTION
+
+ Given a pointer to a string, parse the string extracting fields
+ separated by whitespace and optionally enclosed within either single
+ or double quotes (which are stripped off), and build a vector of
+ pointers to copies of the string for each field. The input string
+ remains unchanged.
+
+ All of the memory for the pointer array and copies of the string
+ is obtained from malloc. All of the memory can be returned to the
+ system with the single function call freeargv, which takes the
+ returned result of buildargv, as it's argument.
+
+ The memory for the argv array is dynamically expanded as necessary.
+
+RETURNS
+
+ Returns a pointer to the argument vector if successful. Returns NULL
+ if the input string pointer is NULL or if there is insufficient
+ memory to complete building the argument vector.
+
+NOTES
+
+ In order to provide a working buffer for extracting arguments into,
+ with appropriate stripping of quotes and translation of backslash
+ sequences, we allocate a working buffer at least as long as the input
+ string. This ensures that we always have enough space in which to
+ work, since the extracted arg is never larger than the input string.
+
+ If the input is a null string (as opposed to a NULL pointer), then
+ buildarg returns an argv that has one arg, a null string.
+
+ Argv is always kept terminated with a NULL arg pointer, so it can
+ be passed to freeargv at any time, or returned, as appropriate.
+*/
+
+char **buildargv (input)
+char *input;
+{
+ char *arg;
+ char *copybuf;
+ int squote = 0;
+ int dquote = 0;
+ int bsquote = 0;
+ int argc = 0;
+ int maxargc = 0;
+ char **argv = NULL;
+ char **nargv;
+
+ if (input != NULL)
+ {
+ copybuf = alloca (strlen (input) + 1);
+ /* Is a do{}while to always execute the loop once. Always return an
+ argv, even for null strings. See NOTES above, test case below. */
+ do
+ {
+ /* Pick off argv[argc] */
+ while (isspace (*input))
+ {
+ input++;
+ }
+ if ((maxargc == 0) || (argc >= (maxargc - 1)))
+ {
+ /* argv needs initialization, or expansion */
+ if (argv == NULL)
+ {
+ maxargc = INITIAL_MAXARGC;
+ nargv = (char **) malloc (maxargc * sizeof (char *));
+ }
+ else
+ {
+ maxargc *= 2;
+ nargv = (char **) realloc (argv, maxargc * sizeof (char *));
+ }
+ if (nargv == NULL)
+ {
+ if (argv != NULL)
+ {
+ freeargv (argv);
+ argv = NULL;
+ }
+ break;
+ }
+ argv = nargv;
+ argv[argc] = NULL;
+ }
+ /* Begin scanning arg */
+ arg = copybuf;
+ while (*input != EOS)
+ {
+ if (isspace (*input) && !squote && !dquote && !bsquote)
+ {
+ break;
+ }
+ else
+ {
+ if (bsquote)
+ {
+ bsquote = 0;
+ *arg++ = *input;
+ }
+ else if (*input == '\\')
+ {
+ bsquote = 1;
+ }
+ else if (squote)
+ {
+ if (*input == '\'')
+ {
+ squote = 0;
+ }
+ else
+ {
+ *arg++ = *input;
+ }
+ }
+ else if (dquote)
+ {
+ if (*input == '"')
+ {
+ dquote = 0;
+ }
+ else
+ {
+ *arg++ = *input;
+ }
+ }
+ else
+ {
+ if (*input == '\'')
+ {
+ squote = 1;
+ }
+ else if (*input == '"')
+ {
+ dquote = 1;
+ }
+ else
+ {
+ *arg++ = *input;
+ }
+ }
+ input++;
+ }
+ }
+ *arg = EOS;
+ argv[argc] = strdup (copybuf);
+ if (argv[argc] == NULL)
+ {
+ freeargv (argv);
+ argv = NULL;
+ break;
+ }
+ argc++;
+ argv[argc] = NULL;
+ }
+ while (*input != EOS);
+ }
+ return (argv);
+}
+
+#ifdef MAIN
+
+/* Simple little test driver. */
+
+static char *tests[] =
+{
+ "a simple command line",
+ "arg 'foo' is single quoted",
+ "arg \"bar\" is double quoted",
+ "arg \"foo bar\" has embedded whitespace",
+ "arg 'Jack said \\'hi\\'' has single quotes",
+ "arg 'Jack said \\\"hi\\\"' has double quotes",
+ "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9",
+ "",
+ NULL
+};
+
+main ()
+{
+ char **argv;
+ char **test;
+ char **targs;
+
+ for (test = tests; *test != NULL; test++)
+ {
+ printf ("buildargv(\"%s\")\n", *test);
+ if ((argv = buildargv (*test)) == NULL)
+ {
+ printf ("failed!\n\n");
+ }
+ else
+ {
+ for (targs = argv; *targs != NULL; targs++)
+ {
+ printf ("\t\"%s\"\n", *targs);
+ }
+ printf ("\n");
+ }
+ freeargv (argv);
+ }
+
+}
+
+#endif /* MAIN */
diff --git a/gnu/usr.bin/gdb/libiberty/basename.c b/gnu/usr.bin/gdb/libiberty/basename.c
new file mode 100644
index 000000000000..f61a308e9b53
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/basename.c
@@ -0,0 +1,56 @@
+/* Return the basename of a pathname.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/*
+
+NAME
+
+ basename -- return pointer to last component of a pathname
+
+SYNOPSIS
+
+ char *basename (char *name)
+
+DESCRIPTION
+
+ Given a pointer to a string containing a typical pathname
+ (/usr/src/cmd/ls/ls.c for example), returns a pointer to the
+ last component of the pathname ("ls.c" in this case).
+
+BUGS
+
+ Presumes a UNIX style path with UNIX style separators.
+*/
+
+
+char *
+basename (name)
+ char *name;
+{
+ char *base = name;
+
+ while (*name)
+ {
+ if (*name++ == '/')
+ {
+ base = name;
+ }
+ }
+ return (base);
+}
diff --git a/gnu/usr.bin/gdb/libiberty/concat.c b/gnu/usr.bin/gdb/libiberty/concat.c
new file mode 100644
index 000000000000..61f7d97481ce
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/concat.c
@@ -0,0 +1,118 @@
+/* Concatenate variable number of strings.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ Written by Fred Fish @ Cygnus Support
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+
+/*
+
+NAME
+
+ concat -- concatenate a variable number of strings
+
+SYNOPSIS
+
+ #include <varargs.h>
+
+ char *concat (s1, s2, s3, ..., NULL)
+
+DESCRIPTION
+
+ Concatenate a variable number of strings and return the result
+ in freshly malloc'd memory.
+
+ Returns NULL if insufficient memory is available. The argument
+ list is terminated by the first NULL pointer encountered. Pointers
+ to empty strings are ignored.
+
+NOTES
+
+ This function uses xmalloc() which is expected to be a front end
+ function to malloc() that deals with low memory situations. In
+ typical use, if malloc() returns NULL then xmalloc() diverts to an
+ error handler routine which never returns, and thus xmalloc will
+ never return a NULL pointer. If the client application wishes to
+ deal with low memory situations itself, it should supply an xmalloc
+ that just directly invokes malloc and blindly returns whatever
+ malloc returns.
+*/
+
+
+#include <varargs.h>
+
+#define NULLP (char *)0
+
+extern char *xmalloc ();
+
+/* VARARGS */
+char *
+concat (va_alist)
+ va_dcl
+{
+ register int length = 0;
+ register char *newstr;
+ register char *end;
+ register char *arg;
+ va_list args;
+
+ /* First compute the size of the result and get sufficient memory. */
+
+ va_start (args);
+ while ((arg = va_arg (args, char *)) != NULLP)
+ {
+ length += strlen (arg);
+ }
+ newstr = (char *) xmalloc (length + 1);
+ va_end (args);
+
+ /* Now copy the individual pieces to the result string. */
+
+ if (newstr != NULLP)
+ {
+ va_start (args);
+ end = newstr;
+ while ((arg = va_arg (args, char *)) != NULLP)
+ {
+ while (*arg)
+ {
+ *end++ = *arg++;
+ }
+ }
+ *end = '\000';
+ va_end (args);
+ }
+
+ return (newstr);
+}
+
+#ifdef MAIN
+
+/* Simple little test driver. */
+
+main ()
+{
+ printf ("\"\" = \"%s\"\n", concat (NULLP));
+ printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
+ printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP));
+ printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP));
+ printf ("\"abcd\" = \"%s\"\n", concat ("ab", "cd", NULLP));
+ printf ("\"abcde\" = \"%s\"\n", concat ("ab", "c", "de", NULLP));
+ printf ("\"abcdef\" = \"%s\"\n", concat ("", "a", "", "bcd", "ef", NULLP));
+}
+
+#endif
diff --git a/gnu/usr.bin/gdb/libiberty/config.h b/gnu/usr.bin/gdb/libiberty/config.h
new file mode 100644
index 000000000000..b37ee84a78ab
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/config.h
@@ -0,0 +1 @@
+/* !Automatically generated from ./functions.def - DO NOT EDIT! */
diff --git a/gnu/usr.bin/gdb/libiberty/cplus-dem.c b/gnu/usr.bin/gdb/libiberty/cplus-dem.c
new file mode 100644
index 000000000000..2ad0e971487b
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/cplus-dem.c
@@ -0,0 +1,2669 @@
+/* Demangler for GNU C++
+ Copyright 1989, 1991 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.uucp)
+ Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
+
+ 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. */
+
+#include <demangle.h>
+#undef CURRENT_DEMANGLING_STYLE
+#define CURRENT_DEMANGLING_STYLE work->options
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+
+extern char *xmalloc PARAMS((long));
+extern char *xrealloc PARAMS((PTR, long));
+extern char *strstr PARAMS ((const char *, const char *));
+extern void free PARAMS((PTR));
+
+/* In order to allow a single demangler executable to demangle strings
+ using various common values of CPLUS_MARKER, as well as any specific
+ one set at compile time, we maintain a string containing all the
+ commonly used ones, and check to see if the marker we are looking for
+ is in that string. CPLUS_MARKER is usually '$' on systems where the
+ assembler can deal with that. Where the assembler can't, it's usually
+ '.' (but on many systems '.' is used for other things). We put the
+ current defined CPLUS_MARKER first (which defaults to '$'), followed
+ by the next most common value, followed by an explicit '$' in case
+ the value of CPLUS_MARKER is not '$'.
+
+ We could avoid this if we could just get g++ to tell us what the actual
+ cplus marker character is as part of the debug information, perhaps by
+ ensuring that it is the character that terminates the gcc<n>_compiled
+ marker symbol (FIXME). */
+
+#if !defined (CPLUS_MARKER)
+#define CPLUS_MARKER '$'
+#endif
+
+enum demangling_styles current_demangling_style = gnu_demangling;
+
+static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
+
+void
+set_cplus_marker_for_demangling (ch)
+ int ch;
+{
+ cplus_markers[0] = ch;
+}
+
+/* Stuff that is shared between sub-routines.
+ * Using a shared structure allows cplus_demangle to be reentrant. */
+
+struct work_stuff
+{
+ int options;
+ char **typevec;
+ int ntypes;
+ int typevec_size;
+ int constructor;
+ int destructor;
+ int static_type; /* A static member function */
+ int const_type; /* A const member function */
+};
+
+#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
+#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
+
+static CONST struct optable
+{
+ CONST char *in;
+ CONST char *out;
+ int flags;
+} optable[] = {
+ {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
+ {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */
+ {"new", " new", 0}, /* old (1.91, and 1.x) */
+ {"delete", " delete", 0}, /* old (1.91, and 1.x) */
+ {"as", "=", DMGL_ANSI}, /* ansi */
+ {"ne", "!=", DMGL_ANSI}, /* old, ansi */
+ {"eq", "==", DMGL_ANSI}, /* old, ansi */
+ {"ge", ">=", DMGL_ANSI}, /* old, ansi */
+ {"gt", ">", DMGL_ANSI}, /* old, ansi */
+ {"le", "<=", DMGL_ANSI}, /* old, ansi */
+ {"lt", "<", DMGL_ANSI}, /* old, ansi */
+ {"plus", "+", 0}, /* old */
+ {"pl", "+", DMGL_ANSI}, /* ansi */
+ {"apl", "+=", DMGL_ANSI}, /* ansi */
+ {"minus", "-", 0}, /* old */
+ {"mi", "-", DMGL_ANSI}, /* ansi */
+ {"ami", "-=", DMGL_ANSI}, /* ansi */
+ {"mult", "*", 0}, /* old */
+ {"ml", "*", DMGL_ANSI}, /* ansi */
+ {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
+ {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
+ {"convert", "+", 0}, /* old (unary +) */
+ {"negate", "-", 0}, /* old (unary -) */
+ {"trunc_mod", "%", 0}, /* old */
+ {"md", "%", DMGL_ANSI}, /* ansi */
+ {"amd", "%=", DMGL_ANSI}, /* ansi */
+ {"trunc_div", "/", 0}, /* old */
+ {"dv", "/", DMGL_ANSI}, /* ansi */
+ {"adv", "/=", DMGL_ANSI}, /* ansi */
+ {"truth_andif", "&&", 0}, /* old */
+ {"aa", "&&", DMGL_ANSI}, /* ansi */
+ {"truth_orif", "||", 0}, /* old */
+ {"oo", "||", DMGL_ANSI}, /* ansi */
+ {"truth_not", "!", 0}, /* old */
+ {"nt", "!", DMGL_ANSI}, /* ansi */
+ {"postincrement","++", 0}, /* old */
+ {"pp", "++", DMGL_ANSI}, /* ansi */
+ {"postdecrement","--", 0}, /* old */
+ {"mm", "--", DMGL_ANSI}, /* ansi */
+ {"bit_ior", "|", 0}, /* old */
+ {"or", "|", DMGL_ANSI}, /* ansi */
+ {"aor", "|=", DMGL_ANSI}, /* ansi */
+ {"bit_xor", "^", 0}, /* old */
+ {"er", "^", DMGL_ANSI}, /* ansi */
+ {"aer", "^=", DMGL_ANSI}, /* ansi */
+ {"bit_and", "&", 0}, /* old */
+ {"ad", "&", DMGL_ANSI}, /* ansi */
+ {"aad", "&=", DMGL_ANSI}, /* ansi */
+ {"bit_not", "~", 0}, /* old */
+ {"co", "~", DMGL_ANSI}, /* ansi */
+ {"call", "()", 0}, /* old */
+ {"cl", "()", DMGL_ANSI}, /* ansi */
+ {"alshift", "<<", 0}, /* old */
+ {"ls", "<<", DMGL_ANSI}, /* ansi */
+ {"als", "<<=", DMGL_ANSI}, /* ansi */
+ {"arshift", ">>", 0}, /* old */
+ {"rs", ">>", DMGL_ANSI}, /* ansi */
+ {"ars", ">>=", DMGL_ANSI}, /* ansi */
+ {"component", "->", 0}, /* old */
+ {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
+ {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
+ {"indirect", "*", 0}, /* old */
+ {"method_call", "->()", 0}, /* old */
+ {"addr", "&", 0}, /* old (unary &) */
+ {"array", "[]", 0}, /* old */
+ {"vc", "[]", DMGL_ANSI}, /* ansi */
+ {"compound", ", ", 0}, /* old */
+ {"cm", ", ", DMGL_ANSI}, /* ansi */
+ {"cond", "?:", 0}, /* old */
+ {"cn", "?:", DMGL_ANSI}, /* psuedo-ansi */
+ {"max", ">?", 0}, /* old */
+ {"mx", ">?", DMGL_ANSI}, /* psuedo-ansi */
+ {"min", "<?", 0}, /* old */
+ {"mn", "<?", DMGL_ANSI}, /* psuedo-ansi */
+ {"nop", "", 0}, /* old (for operator=) */
+ {"rm", "->*", DMGL_ANSI} /* ansi */
+};
+
+
+typedef struct string /* Beware: these aren't required to be */
+{ /* '\0' terminated. */
+ char *b; /* pointer to start of string */
+ char *p; /* pointer after last character */
+ char *e; /* pointer after end of allocated space */
+} string;
+
+#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
+#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
+ string_prepend(str, " ");}
+#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
+ string_append(str, " ");}
+
+#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
+#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
+
+/* Prototypes for local functions */
+
+static char *
+mop_up PARAMS ((struct work_stuff *, string *, int));
+
+#if 0
+static int
+demangle_method_args PARAMS ((struct work_stuff *work, CONST char **, string *));
+#endif
+
+static int
+demangle_template PARAMS ((struct work_stuff *work, CONST char **, string *,
+ string *));
+
+static int
+demangle_qualified PARAMS ((struct work_stuff *, CONST char **, string *,
+ int, int));
+
+static int
+demangle_class PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static int
+demangle_fund_type PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static int
+demangle_signature PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static int
+demangle_prefix PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static int
+gnu_special PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static int
+arm_special PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static void
+string_need PARAMS ((string *, int));
+
+static void
+string_delete PARAMS ((string *));
+
+static void
+string_init PARAMS ((string *));
+
+static void
+string_clear PARAMS ((string *));
+
+#if 0
+static int
+string_empty PARAMS ((string *));
+#endif
+
+static void
+string_append PARAMS ((string *, CONST char *));
+
+static void
+string_appends PARAMS ((string *, string *));
+
+static void
+string_appendn PARAMS ((string *, CONST char *, int));
+
+static void
+string_prepend PARAMS ((string *, CONST char *));
+
+static void
+string_prependn PARAMS ((string *, CONST char *, int));
+
+static int
+get_count PARAMS ((CONST char **, int *));
+
+static int
+consume_count PARAMS ((CONST char **));
+
+static int
+demangle_args PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static int
+do_type PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static int
+do_arg PARAMS ((struct work_stuff *, CONST char **, string *));
+
+static void
+demangle_function_name PARAMS ((struct work_stuff *, CONST char **, string *,
+ CONST char *));
+
+static void
+remember_type PARAMS ((struct work_stuff *, CONST char *, int));
+
+static void
+forget_types PARAMS ((struct work_stuff *));
+
+static void
+string_prepends PARAMS ((string *, string *));
+
+/* Translate count to integer, consuming tokens in the process.
+ Conversion terminates on the first non-digit character.
+ Trying to consume something that isn't a count results in
+ no consumption of input and a return of 0. */
+
+static int
+consume_count (type)
+ CONST char **type;
+{
+ int count = 0;
+
+ while (isdigit (**type))
+ {
+ count *= 10;
+ count += **type - '0';
+ (*type)++;
+ }
+ return (count);
+}
+
+/* Takes operator name as e.g. "++" and returns mangled
+ operator name (e.g. "postincrement_expr"), or NULL if not found.
+
+ If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
+ if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
+
+char *
+cplus_mangle_opname (opname, options)
+ char *opname;
+ int options;
+{
+ int i;
+ int len;
+
+ len = strlen (opname);
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].out) == len
+ && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
+ && memcmp (optable[i].out, opname, len) == 0)
+ return ((char *)optable[i].in);
+ }
+ return (0);
+}
+
+/* check to see whether MANGLED can match TEXT in the first TEXT_LEN
+ characters. */
+
+int cplus_match (mangled, text, text_len)
+ CONST char *mangled;
+ char *text;
+ int text_len;
+{
+ if (strncmp (mangled, text, text_len) != 0) {
+ return(0); /* cannot match either */
+ } else {
+ return(1); /* matches mangled, may match demangled */
+ }
+}
+
+/* char *cplus_demangle (const char *name, int options)
+
+ 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.
+
+ The OPTIONS arg may contain one or more of the following bits:
+
+ DMGL_ANSI ANSI qualifiers such as `const' and `void' are
+ included.
+ DMGL_PARAMS Function parameters are included.
+
+ For example,
+
+ cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", 0) => "A::foo"
+
+ cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", 0) => "A::foo"
+
+ Note that any leading underscores, or other such characters prepended by
+ the compilation system, are presumed to have already been stripped from
+ TYPE. */
+
+char *
+cplus_demangle (mangled, options)
+ CONST char *mangled;
+ int options;
+{
+ string decl;
+ int success = 0;
+ struct work_stuff work[1];
+ char *demangled = NULL;
+
+ if ((mangled != NULL) && (*mangled != '\0'))
+ {
+ memset ((char *) work, 0, sizeof (work));
+ work -> options = options;
+ if ((work->options & DMGL_STYLE_MASK) == 0)
+ work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
+
+ string_init (&decl);
+
+ /* First check to see if gnu style demangling is active and if the
+ string to be demangled contains a CPLUS_MARKER. If so, attempt to
+ recognize one of the gnu special forms rather than looking for a
+ standard prefix. In particular, don't worry about whether there
+ is a "__" string in the mangled string. Consider "_$_5__foo" for
+ example. */
+
+ if ((AUTO_DEMANGLING || GNU_DEMANGLING))
+ {
+ success = gnu_special (work, &mangled, &decl);
+ }
+ if (!success)
+ {
+ success = demangle_prefix (work, &mangled, &decl);
+ }
+ if (success && (*mangled != '\0'))
+ {
+ success = demangle_signature (work, &mangled, &decl);
+ }
+ if (work->constructor == 2)
+ {
+ string_prepend(&decl, "global constructors keyed to ");
+ work->constructor = 0;
+ }
+ else if (work->destructor == 2)
+ {
+ string_prepend(&decl, "global destructors keyed to ");
+ work->destructor = 0;
+ }
+ demangled = mop_up (work, &decl, success);
+ }
+ return (demangled);
+}
+
+static char *
+mop_up (work, declp, success)
+ struct work_stuff *work;
+ string *declp;
+ int success;
+{
+ char *demangled = NULL;
+
+ /* Discard the remembered types, if any. */
+
+ forget_types (work);
+ if (work -> typevec != NULL)
+ {
+ free ((char *) work -> typevec);
+ }
+
+ /* If demangling was successful, ensure that the demangled string is null
+ terminated and return it. Otherwise, free the demangling decl. */
+
+ if (!success)
+ {
+ string_delete (declp);
+ }
+ else
+ {
+ string_appendn (declp, "", 1);
+ demangled = declp -> b;
+ }
+ return (demangled);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_signature -- demangle the signature part of a mangled name
+
+SYNOPSIS
+
+ static int
+ demangle_signature (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+DESCRIPTION
+
+ Consume and demangle the signature portion of the mangled name.
+
+ DECLP is the string where demangled output is being built. At
+ entry it contains the demangled root name from the mangled name
+ prefix. I.E. either a demangled operator name or the root function
+ name. In some special cases, it may contain nothing.
+
+ *MANGLED points to the current unconsumed location in the mangled
+ name. As tokens are consumed and demangling is performed, the
+ pointer is updated to continuously point at the next token to
+ be consumed.
+
+ Demangling GNU style mangled names is nasty because there is no
+ explicit token that marks the start of the outermost function
+ argument list.
+*/
+
+static int
+demangle_signature (work, mangled, declp)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+{
+ int success = 1;
+ int func_done = 0;
+ int expect_func = 0;
+ CONST char *oldmangled = NULL;
+ string trawname;
+ string tname;
+
+ while (success && (**mangled != '\0'))
+ {
+ switch (**mangled)
+ {
+ case 'Q':
+ oldmangled = *mangled;
+ success = demangle_qualified (work, mangled, declp, 1, 0);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ expect_func = 1;
+ }
+ oldmangled = NULL;
+ break;
+
+ case 'S':
+ /* Static member function */
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ (*mangled)++;
+ work -> static_type = 1;
+ break;
+
+ case 'C':
+ /* a const member function */
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ (*mangled)++;
+ work -> const_type = 1;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ success = demangle_class (work, mangled, declp);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ expect_func = 1;
+ }
+ oldmangled = NULL;
+ break;
+
+ case 'F':
+ /* Function */
+ /* ARM style demangling includes a specific 'F' character after
+ the class name. For GNU style, it is just implied. So we can
+ safely just consume any 'F' at this point and be compatible
+ with either style. */
+
+ oldmangled = NULL;
+ func_done = 1;
+ (*mangled)++;
+
+ /* For lucid/ARM style we have to forget any types we might
+ have remembered up to this point, since they were not argument
+ types. GNU style considers all types seen as available for
+ back references. See comment in demangle_args() */
+
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+ forget_types (work);
+ }
+ success = demangle_args (work, mangled, declp);
+ break;
+
+ case 't':
+ /* G++ Template */
+ string_init(&trawname);
+ string_init(&tname);
+ success = demangle_template (work, mangled, &tname, &trawname);
+ string_append(&tname, "::");
+ string_prepends(declp, &tname);
+ if (work -> destructor & 1)
+ {
+ string_prepend (&trawname, "~");
+ string_appends (declp, &trawname);
+ work->destructor -= 1;
+ }
+ if ((work->constructor & 1) || (work->destructor & 1))
+ {
+ string_appends (declp, &trawname);
+ work->constructor -= 1;
+ }
+ string_delete(&trawname);
+ string_delete(&tname);
+ expect_func = 1;
+ break;
+
+ case '_':
+ /* At the outermost level, we cannot have a return type specified,
+ so if we run into another '_' at this point we are dealing with
+ a mangled name that is either bogus, or has been mangled by
+ some algorithm we don't know how to deal with. So just
+ reject the entire demangling. */
+ success = 0;
+ break;
+
+ default:
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ /* Assume we have stumbled onto the first outermost function
+ argument token, and start processing args. */
+ func_done = 1;
+ success = demangle_args (work, mangled, declp);
+ }
+ else
+ {
+ /* Non-GNU demanglers use a specific token to mark the start
+ of the outermost function argument tokens. Typically 'F',
+ for ARM-demangling, for example. So if we find something
+ we are not prepared for, it must be an error. */
+ success = 0;
+ }
+ break;
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ if (success && expect_func)
+ {
+ func_done = 1;
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+ }
+ if (success && !func_done)
+ {
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+ bar__3fooi is 'foo::bar(int)'. We get here when we find the
+ first case, and need to ensure that the '(void)' gets added to
+ the current declp. Note that with ARM, the first case
+ represents the name of a static data member 'foo::bar',
+ which is in the current declp, so we leave it alone. */
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+ if (success && work -> static_type && PRINT_ARG_TYPES)
+ {
+ string_append (declp, " static");
+ }
+ if (success && work -> const_type && PRINT_ARG_TYPES)
+ {
+ string_append (declp, " const");
+ }
+ return (success);
+}
+
+#if 0
+
+static int
+demangle_method_args (work, mangled, declp)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+{
+ int success = 0;
+
+ if (work -> static_type)
+ {
+ string_append (declp, *mangled + 1);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ success = demangle_args (work, mangled, declp);
+ }
+ return (success);
+}
+
+#endif
+
+static int
+demangle_template (work, mangled, tname, trawname)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *tname;
+ string *trawname;
+{
+ int i;
+ int is_pointer;
+ int is_real;
+ int is_integral;
+ int r;
+ int need_comma = 0;
+ int success = 0;
+ int done;
+ CONST char *old_p;
+ CONST char *start;
+ int symbol_len;
+ string temp;
+
+ (*mangled)++;
+ start = *mangled;
+ /* get template name */
+ if ((r = consume_count (mangled)) == 0)
+ {
+ return (0);
+ }
+ if (trawname)
+ string_appendn (trawname, *mangled, r);
+ string_appendn (tname, *mangled, r);
+ *mangled += r;
+ string_append (tname, "<");
+ /* get size of template parameter list */
+ if (!get_count (mangled, &r))
+ {
+ return (0);
+ }
+ for (i = 0; i < r; i++)
+ {
+ if (need_comma)
+ {
+ string_append (tname, ", ");
+ }
+ /* Z for type parameters */
+ if (**mangled == 'Z')
+ {
+ (*mangled)++;
+ /* temp is initialized in do_type */
+ success = do_type (work, mangled, &temp);
+ if (success)
+ {
+ string_appends (tname, &temp);
+ }
+ string_delete(&temp);
+ if (!success)
+ {
+ break;
+ }
+ }
+ else
+ {
+ /* otherwise, value parameter */
+ old_p = *mangled;
+ is_pointer = 0;
+ is_real = 0;
+ is_integral = 0;
+ done = 0;
+ /* temp is initialized in do_type */
+ success = do_type (work, mangled, &temp);
+ if (success)
+ {
+ string_appends (tname, &temp);
+ }
+ string_delete(&temp);
+ if (!success)
+ {
+ break;
+ }
+ string_append (tname, "=");
+ while (*old_p && !done)
+ {
+ switch (*old_p)
+ {
+ case 'P':
+ case 'R':
+ done = is_pointer = 1;
+ break;
+ case 'C': /* const */
+ case 'S': /* explicitly signed [char] */
+ case 'U': /* unsigned */
+ case 'V': /* volatile */
+ case 'F': /* function */
+ case 'M': /* member function */
+ case 'O': /* ??? */
+ old_p++;
+ continue;
+ case 'Q': /* repetition of following */
+ case 'T': /* remembered type */
+ abort ();
+ break;
+ case 'v': /* void */
+ abort ();
+ break;
+ case 'x': /* long long */
+ case 'l': /* long */
+ case 'i': /* int */
+ case 's': /* short */
+ case 'c': /* char */
+ case 'w': /* wchar_t */
+ done = is_integral = 1;
+ break;
+ case 'r': /* long double */
+ case 'd': /* double */
+ case 'f': /* float */
+ done = is_real = 1;
+ break;
+ default:
+ abort ();
+ }
+ }
+ if (is_integral)
+ {
+ if (**mangled == 'm')
+ {
+ string_appendn (tname, "-", 1);
+ (*mangled)++;
+ }
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ else if (is_real)
+ {
+ if (**mangled == 'm')
+ {
+ string_appendn (tname, "-", 1);
+ (*mangled)++;
+ }
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ if (**mangled == '.') /* fraction */
+ {
+ string_appendn (tname, ".", 1);
+ (*mangled)++;
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ if (**mangled == 'e') /* exponent */
+ {
+ string_appendn (tname, "e", 1);
+ (*mangled)++;
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ }
+ else if (is_pointer)
+ {
+ if (!get_count (mangled, &symbol_len))
+ {
+ success = 0;
+ break;
+ }
+ string_appendn (tname, *mangled, symbol_len);
+ *mangled += symbol_len;
+ }
+ }
+ need_comma = 1;
+ }
+ string_append (tname, ">");
+
+/*
+ if (work -> static_type)
+ {
+ string_append (declp, *mangled + 1);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+*/
+ return (success);
+}
+
+static int
+arm_pt (work, mangled, n, anchor, args)
+ struct work_stuff *work;
+ CONST char *mangled;
+ int n;
+ CONST char **anchor, **args;
+{
+ /* ARM template? */
+ if (ARM_DEMANGLING && (*anchor = strstr(mangled, "__pt__")))
+ {
+ int len;
+ *args = *anchor + 6;
+ len = consume_count (args);
+ if (*args + len == mangled + n && **args == '_')
+ {
+ ++*args;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+demangle_class_name (work, mangled, declp)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 0;
+
+ n = consume_count (mangled);
+ if (strlen (*mangled) >= n)
+ {
+ CONST char *p;
+ CONST char *args;
+ CONST char *e = *mangled + n;
+ /* ARM template? */
+ if (arm_pt (work, *mangled, n, &p, &args))
+ {
+ string arg;
+ string_init (&arg);
+ string_appendn (declp, *mangled, p - *mangled);
+ string_append (declp, "<");
+ /* should do error checking here */
+ while (args < e) {
+ string_clear (&arg);
+ do_type (work, &args, &arg);
+ string_appends (declp, &arg);
+ string_append (declp, ",");
+ }
+ string_delete (&arg);
+ --declp->p;
+ string_append (declp, ">");
+ }
+ else
+ {
+ string_appendn (declp, *mangled, n);
+ }
+ *mangled += n;
+ success = 1;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_class -- demangle a mangled class sequence
+
+SYNOPSIS
+
+ static int
+ demangle_class (struct work_stuff *work, const char **mangled,
+ strint *declp)
+
+DESCRIPTION
+
+ DECLP points to the buffer into which demangling is being done.
+
+ *MANGLED points to the current token to be demangled. On input,
+ it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
+ On exit, it points to the next token after the mangled class on
+ success, or the first unconsumed token on failure.
+
+ If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
+ we are demangling a constructor or destructor. In this case
+ we prepend "class::class" or "class::~class" to DECLP.
+
+ Otherwise, we prepend "class::" to the current DECLP.
+
+ Reset the constructor/destructor flags once they have been
+ "consumed". This allows demangle_class to be called later during
+ the same demangling, to do normal class demangling.
+
+ Returns 1 if demangling is successful, 0 otherwise.
+
+*/
+
+static int
+demangle_class (work, mangled, declp)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+{
+ int success = 0;
+ string class_name;
+
+ string_init (&class_name);
+ if (demangle_class_name (work, mangled, &class_name))
+ {
+ if ((work->constructor & 1) || (work->destructor & 1))
+ {
+ string_prepends (declp, &class_name);
+ if (work -> destructor & 1)
+ {
+ string_prepend (declp, "~");
+ work -> destructor -= 1;
+ }
+ else
+ {
+ work -> constructor -= 1;
+ }
+ }
+ string_prepend (declp, "::");
+ string_prepends (declp, &class_name);
+ success = 1;
+ }
+ string_delete (&class_name);
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_prefix -- consume the mangled name prefix and find signature
+
+SYNOPSIS
+
+ static int
+ demangle_prefix (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+DESCRIPTION
+
+ Consume and demangle the prefix of the mangled name.
+
+ DECLP points to the string buffer into which demangled output is
+ placed. On entry, the buffer is empty. On exit it contains
+ the root function name, the demangled operator name, or in some
+ special cases either nothing or the completely demangled result.
+
+ MANGLED points to the current pointer into the mangled name. As each
+ token of the mangled name is consumed, it is updated. Upon entry
+ the current mangled name pointer points to the first character of
+ the mangled name. Upon exit, it should point to the first character
+ of the signature if demangling was successful, or to the first
+ unconsumed character if demangling of the prefix was unsuccessful.
+
+ Returns 1 on success, 0 otherwise.
+ */
+
+static int
+demangle_prefix (work, mangled, declp)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+{
+ int success = 1;
+ CONST char *scan;
+ int i;
+
+ if (strncmp(*mangled, "_GLOBAL_$D$", 11) == 0)
+ {
+ /* it's a GNU global destructor to be executed at program exit */
+ (*mangled) += 11;
+ work->destructor = 2;
+ }
+ else if (strncmp(*mangled, "_GLOBAL_$I$", 11) == 0)
+ {
+ /* it's a GNU global constructor to be executed at program initial */
+ (*mangled) += 11;
+ work->constructor = 2;
+ }
+ else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
+ {
+ /* it's a ARM global destructor to be executed at program exit */
+ (*mangled) += 7;
+ work->destructor = 2;
+ }
+ else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
+ {
+ /* it's a ARM global constructor to be executed at program initial */
+ (*mangled) += 7;
+ work->constructor = 2;
+ }
+
+/* This block of code is a reduction in strength time optimization
+ of:
+ scan = strstr (*mangled, "__"); */
+
+ {
+ scan = *mangled;
+
+ do {
+ scan = strchr (scan, '_');
+ } while (scan != NULL && *++scan != '_');
+
+ if (scan != NULL) --scan;
+ }
+
+ if (scan != NULL)
+ {
+ /* We found a sequence of two or more '_', ensure that we start at
+ the last pair in the sequence. */
+ i = strspn (scan, "_");
+ if (i > 2)
+ {
+ scan += (i - 2);
+ }
+ }
+
+ if (scan == NULL)
+ {
+ success = 0;
+ }
+ else if (work -> static_type)
+ {
+ if (!isdigit (scan[0]) && (scan[0] != 't'))
+ {
+ success = 0;
+ }
+ }
+ else if ((scan == *mangled) &&
+ (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
+ {
+ /* The ARM says nothing about the mangling of local variables.
+ But cfront mangles local variables by prepending __<nesting_level>
+ to them. As an extension to ARM demangling we handle this case. */
+ if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
+ {
+ *mangled = scan + 2;
+ consume_count (mangled);
+ string_append (declp, *mangled);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ /* A GNU style constructor starts with "__[0-9Qt]. */
+ work -> constructor += 1;
+ *mangled = scan + 2;
+ }
+ }
+ else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't'))
+ {
+ /* Mangled name starts with "__". Skip over any leading '_' characters,
+ then find the next "__" that separates the prefix from the signature.
+ */
+ if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
+ || (arm_special (work, mangled, declp) == 0))
+ {
+ while (*scan == '_')
+ {
+ scan++;
+ }
+ if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
+ {
+ /* No separator (I.E. "__not_mangled"), or empty signature
+ (I.E. "__not_mangled_either__") */
+ success = 0;
+ }
+ else
+ {
+ demangle_function_name (work, mangled, declp, scan);
+ }
+ }
+ }
+ else if (*(scan + 2) != '\0')
+ {
+ /* Mangled name does not start with "__" but does have one somewhere
+ in there with non empty stuff after it. Looks like a global
+ function name. */
+ demangle_function_name (work, mangled, declp, scan);
+ }
+ else
+ {
+ /* Doesn't look like a mangled name */
+ success = 0;
+ }
+
+ if (!success && (work->constructor == 2 || work->destructor == 2))
+ {
+ string_append (declp, *mangled);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ gnu_special -- special handling of gnu mangled strings
+
+SYNOPSIS
+
+ static int
+ gnu_special (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+
+DESCRIPTION
+
+ Process some special GNU style mangling forms that don't fit
+ the normal pattern. For example:
+
+ _$_3foo (destructor for class foo)
+ _vt$foo (foo virtual table)
+ _vt$foo$bar (foo::bar virtual table)
+ _3foo$varname (static data member)
+ _Q22rs2tu$vw (static data member)
+ __t6vector1Zii (constructor with template)
+ */
+
+static int
+gnu_special (work, mangled, declp)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 1;
+ CONST char *p;
+
+ if ((*mangled)[0] == '_'
+ && strchr (cplus_markers, (*mangled)[1]) != NULL
+ && (*mangled)[2] == '_')
+ {
+ /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
+ (*mangled) += 3;
+ work -> destructor += 1;
+ }
+ else if ((*mangled)[0] == '_'
+ && (*mangled)[1] == 'v'
+ && (*mangled)[2] == 't'
+ && strchr (cplus_markers, (*mangled)[3]) != NULL)
+ {
+ /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
+ and create the decl. Note that we consume the entire mangled
+ input string, which means that demangle_signature has no work
+ to do. */
+ (*mangled) += 4;
+ while (**mangled != '\0')
+ {
+ if (isdigit(*mangled[0]))
+ {
+ n = consume_count(mangled);
+ }
+ else
+ {
+ n = strcspn (*mangled, cplus_markers);
+ }
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
+
+ if (**mangled != '\0')
+ {
+ string_append (declp, "::");
+ (*mangled)++;
+ }
+ }
+ string_append (declp, " virtual table");
+ }
+ else if ((*mangled)[0] == '_'
+ && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
+ && (p = strpbrk (*mangled, cplus_markers)) != NULL)
+ {
+ /* static data member, "_3foo$varname" for example */
+ (*mangled)++;
+ switch (**mangled)
+ {
+ case 'Q':
+ success = demangle_qualified (work, mangled, declp, 0, 1);
+ break;
+ case 't':
+ success = demangle_template (work, mangled, declp, 0);
+ break;
+ default:
+ n = consume_count (mangled);
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
+ }
+ if (success && (p == *mangled))
+ {
+ /* Consumed everything up to the cplus_marker, append the
+ variable name. */
+ (*mangled)++;
+ string_append (declp, "::");
+ n = strlen (*mangled);
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
+ }
+ else
+ {
+ success = 0;
+ }
+ }
+ else
+ {
+ success = 0;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ arm_special -- special handling of ARM/lucid mangled strings
+
+SYNOPSIS
+
+ static int
+ arm_special (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+
+DESCRIPTION
+
+ Process some special ARM style mangling forms that don't fit
+ the normal pattern. For example:
+
+ __vtbl__3foo (foo virtual table)
+ __vtbl__3foo__3bar (bar::foo virtual table)
+
+ */
+
+static int
+arm_special (work, mangled, declp)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 1;
+ CONST char *scan;
+
+ if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
+ {
+ /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
+ and create the decl. Note that we consume the entire mangled
+ input string, which means that demangle_signature has no work
+ to do. */
+ scan = *mangled + ARM_VTABLE_STRLEN;
+ while (*scan != '\0') /* first check it can be demangled */
+ {
+ n = consume_count (&scan);
+ if (n==0)
+ {
+ return (0); /* no good */
+ }
+ scan += n;
+ if (scan[0] == '_' && scan[1] == '_')
+ {
+ scan += 2;
+ }
+ }
+ (*mangled) += ARM_VTABLE_STRLEN;
+ while (**mangled != '\0')
+ {
+ n = consume_count (mangled);
+ string_prependn (declp, *mangled, n);
+ (*mangled) += n;
+ if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
+ {
+ string_prepend (declp, "::");
+ (*mangled) += 2;
+ }
+ }
+ string_append (declp, " virtual table");
+ }
+ else
+ {
+ success = 0;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_qualified -- demangle 'Q' qualified name strings
+
+SYNOPSIS
+
+ static int
+ demangle_qualified (struct work_stuff *, const char *mangled,
+ string *result, int isfuncname, int append);
+
+DESCRIPTION
+
+ Demangle a qualified name, such as "Q25Outer5Inner" which is
+ the mangled form of "Outer::Inner". The demangled output is
+ prepended or appended to the result string according to the
+ state of the append flag.
+
+ If isfuncname is nonzero, then the qualified name we are building
+ is going to be used as a member function name, so if it is a
+ constructor or destructor function, append an appropriate
+ constructor or destructor name. I.E. for the above example,
+ the result for use as a constructor is "Outer::Inner::Inner"
+ and the result for use as a destructor is "Outer::Inner::~Inner".
+
+BUGS
+
+ Numeric conversion is ASCII dependent (FIXME).
+
+ */
+
+static int
+demangle_qualified (work, mangled, result, isfuncname, append)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *result;
+ int isfuncname;
+ int append;
+{
+ int qualifiers;
+ int namelength;
+ int success = 1;
+ CONST char *p;
+ char num[2];
+ string temp;
+
+ string_init (&temp);
+ switch ((*mangled)[1])
+ {
+ case '_':
+ /* GNU mangled name with more than 9 classes. The count is preceded
+ by an underscore (to distinguish it from the <= 9 case) and followed
+ by an underscore. */
+ p = *mangled + 2;
+ qualifiers = atoi (p);
+ if (!isdigit (*p) || *p == '0')
+ success = 0;
+
+ /* Skip the digits. */
+ while (isdigit (*p))
+ ++p;
+
+ if (*p != '_')
+ success = 0;
+
+ *mangled = p + 1;
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* The count is in a single digit. */
+ num[0] = (*mangled)[1];
+ num[1] = '\0';
+ qualifiers = atoi (num);
+
+ /* If there is an underscore after the digit, skip it. This is
+ said to be for ARM-qualified names, but the ARM makes no
+ mention of such an underscore. Perhaps cfront uses one. */
+ if ((*mangled)[2] == '_')
+ {
+ (*mangled)++;
+ }
+ (*mangled) += 2;
+ break;
+
+ case '0':
+ default:
+ success = 0;
+ }
+
+ if (!success)
+ return success;
+
+ /* Pick off the names and collect them in the temp buffer in the order
+ in which they are found, separated by '::'. */
+
+ while (qualifiers-- > 0)
+ {
+ if (*mangled[0] == 't')
+ {
+ success = demangle_template(work, mangled, &temp, 0);
+ if (!success) break;
+ }
+ else
+ {
+ namelength = consume_count (mangled);
+ if (strlen (*mangled) < namelength)
+ {
+ /* Simple sanity check failed */
+ success = 0;
+ break;
+ }
+ string_appendn (&temp, *mangled, namelength);
+ *mangled += namelength;
+ }
+ if (qualifiers > 0)
+ {
+ string_appendn (&temp, "::", 2);
+ }
+ }
+
+ /* If we are using the result as a function name, we need to append
+ the appropriate '::' separated constructor or destructor name.
+ We do this here because this is the most convenient place, where
+ we already have a pointer to the name and the length of the name. */
+
+ if (isfuncname && (work->constructor & 1 || work->destructor & 1))
+ {
+ string_appendn (&temp, "::", 2);
+ if (work -> destructor & 1)
+ {
+ string_append (&temp, "~");
+ }
+ string_appendn (&temp, (*mangled) - namelength, namelength);
+ }
+
+ /* Now either prepend the temp buffer to the result, or append it,
+ depending upon the state of the append flag. */
+
+ if (append)
+ {
+ string_appends (result, &temp);
+ }
+ else
+ {
+ if (!STRING_EMPTY (result))
+ {
+ string_appendn (&temp, "::", 2);
+ }
+ string_prepends (result, &temp);
+ }
+
+ string_delete (&temp);
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ get_count -- convert an ascii count to integer, consuming tokens
+
+SYNOPSIS
+
+ static int
+ get_count (const char **type, int *count)
+
+DESCRIPTION
+
+ Return 0 if no conversion is performed, 1 if a string is converted.
+*/
+
+static int
+get_count (type, count)
+ CONST char **type;
+ int *count;
+{
+ CONST char *p;
+ int n;
+
+ if (!isdigit (**type))
+ {
+ return (0);
+ }
+ else
+ {
+ *count = **type - '0';
+ (*type)++;
+ if (isdigit (**type))
+ {
+ p = *type;
+ n = *count;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p++;
+ }
+ 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 (work, mangled, result)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *result;
+{
+ int n;
+ int done;
+ int success;
+ string decl;
+ CONST char *remembered_type;
+ int constp;
+ int volatilep;
+
+ string_init (&decl);
+ string_init (result);
+
+ done = 0;
+ success = 1;
+ while (success && !done)
+ {
+ int member;
+ switch (**mangled)
+ {
+
+ /* A pointer type */
+ case 'P':
+ (*mangled)++;
+ string_prepend (&decl, "*");
+ break;
+
+ /* A reference type */
+ case 'R':
+ (*mangled)++;
+ string_prepend (&decl, "&");
+ break;
+
+ /* An array */
+ case 'A':
+ {
+ CONST char *p = ++(*mangled);
+
+ string_prepend (&decl, "(");
+ string_append (&decl, ")[");
+ /* Copy anything up until the next underscore (the size of the
+ array). */
+ while (**mangled && **mangled != '_')
+ ++(*mangled);
+ if (**mangled == '_')
+ {
+ string_appendn (&decl, p, *mangled - p);
+ string_append (&decl, "]");
+ *mangled += 1;
+ }
+ else
+ success = 0;
+ break;
+ }
+
+ /* A back reference to a previously seen type */
+ case 'T':
+ (*mangled)++;
+ if (!get_count (mangled, &n) || n >= work -> ntypes)
+ {
+ success = 0;
+ }
+ else
+ {
+ remembered_type = work -> typevec[n];
+ mangled = &remembered_type;
+ }
+ break;
+
+ /* A function */
+ case 'F':
+ (*mangled)++;
+ if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
+ {
+ string_prepend (&decl, "(");
+ string_append (&decl, ")");
+ }
+ /* After picking off the function args, we expect to either find the
+ function return type (preceded by an '_') or the end of the
+ string. */
+ if (!demangle_args (work, mangled, &decl)
+ || (**mangled != '_' && **mangled != '\0'))
+ {
+ success = 0;
+ }
+ if (success && (**mangled == '_'))
+ {
+ (*mangled)++;
+ }
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ constp = 0;
+ volatilep = 0;
+
+ member = **mangled == 'M';
+ (*mangled)++;
+ if (!isdigit (**mangled))
+ {
+ success = 0;
+ break;
+ }
+ n = consume_count (mangled);
+ if (strlen (*mangled) < n)
+ {
+ success = 0;
+ break;
+ }
+ string_append (&decl, ")");
+ string_prepend (&decl, "::");
+ string_prependn (&decl, *mangled, n);
+ string_prepend (&decl, "(");
+ *mangled += n;
+ if (member)
+ {
+ if (**mangled == 'C')
+ {
+ (*mangled)++;
+ constp = 1;
+ }
+ if (**mangled == 'V')
+ {
+ (*mangled)++;
+ volatilep = 1;
+ }
+ if (*(*mangled)++ != 'F')
+ {
+ success = 0;
+ break;
+ }
+ }
+ if ((member && !demangle_args (work, mangled, &decl))
+ || **mangled != '_')
+ {
+ success = 0;
+ break;
+ }
+ (*mangled)++;
+ if (! PRINT_ANSI_QUALIFIERS)
+ {
+ break;
+ }
+ if (constp)
+ {
+ APPEND_BLANK (&decl);
+ string_append (&decl, "const");
+ }
+ if (volatilep)
+ {
+ APPEND_BLANK (&decl);
+ string_append (&decl, "volatile");
+ }
+ break;
+ }
+ case 'G':
+ (*mangled)++;
+ break;
+
+ case 'C':
+ (*mangled)++;
+/*
+ if ((*mangled)[1] == 'P')
+ {
+*/
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ if (!STRING_EMPTY (&decl))
+ {
+ string_prepend (&decl, " ");
+ }
+ string_prepend (&decl, "const");
+ }
+ break;
+/*
+ }
+*/
+
+ /* fall through */
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ switch (**mangled)
+ {
+ /* A qualified name, such as "Outer::Inner". */
+ case 'Q':
+ success = demangle_qualified (work, mangled, result, 0, 1);
+ break;
+
+ default:
+ success = demangle_fund_type (work, mangled, result);
+ break;
+ }
+
+ if (success)
+ {
+ if (!STRING_EMPTY (&decl))
+ {
+ string_append (result, " ");
+ string_appends (result, &decl);
+ }
+ }
+ else
+ {
+ string_delete (result);
+ }
+ string_delete (&decl);
+ return (success);
+}
+
+/* Given a pointer to a type string that represents a fundamental type
+ argument (int, long, unsigned int, etc) in TYPE, a pointer to the
+ string in which the demangled output is being built in RESULT, and
+ the WORK structure, decode the types and add them to the result.
+
+ For example:
+
+ "Ci" => "const int"
+ "Sl" => "signed long"
+ "CUs" => "const unsigned short"
+
+ */
+
+static int
+demangle_fund_type (work, mangled, result)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *result;
+{
+ int done = 0;
+ int success = 1;
+
+ /* First pick off any type qualifiers. There can be more than one. */
+
+ while (!done)
+ {
+ switch (**mangled)
+ {
+ case 'C':
+ (*mangled)++;
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ APPEND_BLANK (result);
+ string_append (result, "const");
+ }
+ break;
+ case 'U':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "unsigned");
+ break;
+ case 'S': /* signed char only */
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "signed");
+ break;
+ case 'V':
+ (*mangled)++;
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ APPEND_BLANK (result);
+ string_append (result, "volatile");
+ }
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ /* Now pick off the fundamental type. There can be only one. */
+
+ switch (**mangled)
+ {
+ case '\0':
+ case '_':
+ break;
+ case 'v':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "void");
+ break;
+ case 'x':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long long");
+ break;
+ case 'l':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long");
+ break;
+ case 'i':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "int");
+ break;
+ case 's':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "short");
+ break;
+ case 'c':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "char");
+ break;
+ case 'w':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "wchar_t");
+ break;
+ case 'r':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long double");
+ break;
+ case 'd':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "double");
+ break;
+ case 'f':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "float");
+ break;
+ case 'G':
+ (*mangled)++;
+ if (!isdigit (**mangled))
+ {
+ success = 0;
+ break;
+ }
+ /* fall through */
+ /* An explicit type, such as "6mytype" or "7integer" */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ APPEND_BLANK (result);
+ if (!demangle_class_name (work, mangled, result)) {
+ --result->p;
+ success = 0;
+ }
+ break;
+ case 't':
+ success = demangle_template(work,mangled, result, 0);
+ break;
+ default:
+ success = 0;
+ break;
+ }
+
+ return (success);
+}
+
+/* `result' will be initialized in do_type; it will be freed on failure */
+
+static int
+do_arg (work, mangled, result)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *result;
+{
+ CONST char *start = *mangled;
+
+ if (!do_type (work, mangled, result))
+ {
+ return (0);
+ }
+ else
+ {
+ remember_type (work, start, *mangled - start);
+ return (1);
+ }
+}
+
+static void
+remember_type (work, start, len)
+ struct work_stuff *work;
+ CONST char *start;
+ int len;
+{
+ char *tem;
+
+ if (work -> ntypes >= work -> typevec_size)
+ {
+ if (work -> typevec_size == 0)
+ {
+ work -> typevec_size = 3;
+ work -> typevec =
+ (char **) xmalloc (sizeof (char *) * work -> typevec_size);
+ }
+ else
+ {
+ work -> typevec_size *= 2;
+ work -> typevec =
+ (char **) xrealloc ((char *)work -> typevec,
+ sizeof (char *) * work -> typevec_size);
+ }
+ }
+ tem = xmalloc (len + 1);
+ memcpy (tem, start, len);
+ tem[len] = '\0';
+ work -> typevec[work -> ntypes++] = tem;
+}
+
+/* Forget the remembered types, but not the type vector itself. */
+
+static void
+forget_types (work)
+ struct work_stuff *work;
+{
+ int i;
+
+ while (work -> ntypes > 0)
+ {
+ i = --(work -> ntypes);
+ if (work -> typevec[i] != NULL)
+ {
+ free (work -> typevec[i]);
+ work -> typevec[i] = NULL;
+ }
+ }
+}
+
+/* Process the argument list part of the signature, after any class spec
+ has been consumed, as well as the first 'F' character (if any). For
+ example:
+
+ "__als__3fooRT0" => process "RT0"
+ "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
+
+ DECLP must be already initialised, usually non-empty. It won't be freed
+ on failure.
+
+ Note that g++ differs significantly from ARM and lucid style mangling
+ with regards to references to previously seen types. For example, given
+ the source fragment:
+
+ class foo {
+ public:
+ foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
+ };
+
+ foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+ void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+
+ g++ produces the names:
+
+ __3fooiRT0iT2iT2
+ foo__FiR3fooiT1iT1
+
+ while lcc (and presumably other ARM style compilers as well) produces:
+
+ foo__FiR3fooT1T2T1T2
+ __ct__3fooFiR3fooT1T2T1T2
+
+ Note that g++ bases it's type numbers starting at zero and counts all
+ previously seen types, while lucid/ARM bases it's type numbers starting
+ at one and only considers types after it has seen the 'F' character
+ indicating the start of the function args. For lucid/ARM style, we
+ account for this difference by discarding any previously seen types when
+ we see the 'F' character, and subtracting one from the type number
+ reference.
+
+ */
+
+static int
+demangle_args (work, mangled, declp)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+{
+ string arg;
+ int need_comma = 0;
+ int r;
+ int t;
+ CONST char *tem;
+ char temptype;
+
+ if (PRINT_ARG_TYPES)
+ {
+ string_append (declp, "(");
+ if (**mangled == '\0')
+ {
+ string_append (declp, "void");
+ }
+ }
+
+ while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
+ {
+ if ((**mangled == 'N') || (**mangled == 'T'))
+ {
+ temptype = *(*mangled)++;
+
+ if (temptype == 'N')
+ {
+ if (!get_count (mangled, &r))
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ r = 1;
+ }
+ if (!get_count (mangled, &t))
+ {
+ return (0);
+ }
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+ t--;
+ }
+ /* Validate the type index. Protect against illegal indices from
+ malformed type strings. */
+ if ((t < 0) || (t >= work -> ntypes))
+ {
+ return (0);
+ }
+ while (--r >= 0)
+ {
+ tem = work -> typevec[t];
+ if (need_comma && PRINT_ARG_TYPES)
+ {
+ string_append (declp, ", ");
+ }
+ if (!do_arg (work, &tem, &arg))
+ {
+ return (0);
+ }
+ if (PRINT_ARG_TYPES)
+ {
+ string_appends (declp, &arg);
+ }
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+ else
+ {
+ if (need_comma & PRINT_ARG_TYPES)
+ {
+ string_append (declp, ", ");
+ }
+ if (!do_arg (work, mangled, &arg))
+ {
+ return (0);
+ }
+ if (PRINT_ARG_TYPES)
+ {
+ string_appends (declp, &arg);
+ }
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+
+ if (**mangled == 'e')
+ {
+ (*mangled)++;
+ if (PRINT_ARG_TYPES)
+ {
+ if (need_comma)
+ {
+ string_append (declp, ",");
+ }
+ string_append (declp, "...");
+ }
+ }
+
+ if (PRINT_ARG_TYPES)
+ {
+ string_append (declp, ")");
+ }
+ return (1);
+}
+
+static void
+demangle_function_name (work, mangled, declp, scan)
+ struct work_stuff *work;
+ CONST char **mangled;
+ string *declp;
+ CONST char *scan;
+{
+ int i;
+ int len;
+ string type;
+ CONST char *tem;
+
+ string_appendn (declp, (*mangled), scan - (*mangled));
+ string_need (declp, 1);
+ *(declp -> p) = '\0';
+
+ /* Consume the function name, including the "__" separating the name
+ from the signature. We are guaranteed that SCAN points to the
+ separator. */
+
+ (*mangled) = scan + 2;
+
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+
+ /* See if we have an ARM style constructor or destructor operator.
+ If so, then just record it, clear the decl, and return.
+ We can't build the actual constructor/destructor decl until later,
+ when we recover the class name from the signature. */
+
+ if (strcmp (declp -> b, "__ct") == 0)
+ {
+ work -> constructor += 1;
+ string_clear (declp);
+ return;
+ }
+ else if (strcmp (declp -> b, "__dt") == 0)
+ {
+ work -> destructor += 1;
+ string_clear (declp);
+ return;
+ }
+ }
+
+ if (declp->p - declp->b >= 3
+ && declp->b[0] == 'o'
+ && declp->b[1] == 'p'
+ && strchr (cplus_markers, declp->b[2]) != NULL)
+ {
+ /* see if it's an assignment expression */
+ if (declp->p - declp->b >= 10 /* op$assign_ */
+ && memcmp (declp->b + 3, "assign_", 7) == 0)
+ {
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ len = declp->p - declp->b - 10;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, declp->b + 10, len) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ string_append (declp, "=");
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ int len = declp->p - declp->b - 3;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, declp->b + 3, len) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ }
+ else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type$", 5) == 0)
+ {
+ /* type conversion operator */
+ tem = declp->b + 5;
+ if (do_type (work, &tem, &type))
+ {
+ string_clear (declp);
+ string_append (declp, "operator ");
+ string_appends (declp, &type);
+ string_delete (&type);
+ }
+ }
+ else if (declp->b[0] == '_' && declp->b[1] == '_'
+ && declp->b[2] == 'o' && declp->b[3] == 'p')
+ {
+ /* ANSI. */
+ /* type conversion operator. */
+ tem = declp->b + 4;
+ if (do_type (work, &tem, &type))
+ {
+ string_clear (declp);
+ string_append (declp, "operator ");
+ string_appends (declp, &type);
+ string_delete (&type);
+ }
+ }
+ else if (declp->b[0] == '_' && declp->b[1] == '_'
+ && declp->b[2] >= 'a' && declp->b[2] <= 'z'
+ && declp->b[3] >= 'a' && declp->b[3] <= 'z')
+ {
+ if (declp->b[4] == '\0')
+ {
+ /* Operator. */
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].in) == 2
+ && memcmp (optable[i].in, declp->b + 2, 2) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (declp->b[2] == 'a' && declp->b[5] == '\0')
+ {
+ /* Assignment. */
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].in) == 3
+ && memcmp (optable[i].in, declp->b + 2, 3) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+ string *s;
+ int n;
+{
+ int tem;
+
+ if (s->b == NULL)
+ {
+ if (n < 32)
+ {
+ n = 32;
+ }
+ s->p = s->b = xmalloc (n);
+ s->e = s->b + n;
+ }
+ else if (s->e - s->p < n)
+ {
+ tem = s->p - s->b;
+ n += tem;
+ n *= 2;
+ s->b = 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;
+}
+
+#if 0
+
+static int
+string_empty (s)
+ string *s;
+{
+ return (s->b == s->p);
+}
+
+#endif
+
+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)
+ {
+ 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)
+ {
+ 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')
+ {
+ string_prependn (p, s, strlen (s));
+ }
+}
+
+static void
+string_prepends (p, s)
+ string *p, *s;
+{
+ if (s->b != s->p)
+ {
+ string_prependn (p, s->b, s->p - s->b);
+ }
+}
+
+static void
+string_prependn (p, s, n)
+ string *p;
+ CONST char *s;
+ int n;
+{
+ char *q;
+
+ if (n != 0)
+ {
+ 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;
+ }
+}
+
+/* To generate a standalone demangler program for testing purposes, just
+ compile and link this file with -DMAIN. When run, it demangles each
+ command line arg, or each stdin string, and prints the result on stdout. */
+
+#ifdef MAIN
+
+static void
+demangle_it (mangled_name)
+ char *mangled_name;
+{
+ char *result;
+
+ result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
+ if (result == NULL)
+ {
+ printf ("%s\n", mangled_name);
+ }
+ else
+ {
+ printf ("%s\n", result);
+ free (result);
+ }
+}
+
+char *
+xmalloc (size)
+ long size;
+{
+ char * newmem;
+
+ if ((newmem = (char *) malloc ((int) size)) == NULL)
+ {
+ fprintf (stderr, "\nCan't allocate %u bytes\n", size);
+ exit (1);
+ }
+ return (newmem);
+}
+
+char *
+xrealloc (oldmem, size)
+ PTR oldmem;
+ long size;
+{
+ char * newmem;
+
+ if ((newmem = (char *) realloc ((char *) oldmem, (int) size)) == NULL)
+ {
+ fprintf (stderr, "\nCan't reallocate %u bytes\n", size);
+ exit (1);
+ }
+ return (newmem);
+}
+
+#include "getopt.h"
+
+static char *program_name;
+extern char *program_version;
+
+static void
+usage (stream, status)
+ FILE *stream;
+ int status;
+{
+ fprintf (stream, "\
+Usage: %s [-_] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
+ [--format={gnu,lucid,arm}] [--help] [--version] [arg...]\n",
+ program_name);
+ exit (status);
+}
+
+#define MBUF_SIZE 512
+char mbuffer[MBUF_SIZE];
+
+/* Defined in the automatically-generated ../binutils/underscore.c. */
+extern int prepends_underscore;
+
+int strip_underscore = 0;
+
+static struct option long_options[] = {
+ {"strip-underscores", no_argument, 0, '_'},
+ {"format", required_argument, 0, 's'},
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, no_argument, 0, 0}
+};
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *result;
+ int c;
+
+ program_name = argv[0];
+ strip_underscore = prepends_underscore;
+
+ while ((c = getopt_long (argc, argv, "_s:", long_options, (int *) 0)) != EOF)
+ {
+ switch (c)
+ {
+ case '?':
+ usage (stderr, 1);
+ break;
+ case 'h':
+ usage (stdout, 0);
+ case 'v':
+ printf ("GNU %s version %s\n", program_name, program_version);
+ exit (0);
+ case '_':
+ strip_underscore = 1;
+ break;
+ case 's':
+ if (strcmp (optarg, "gnu") == 0)
+ {
+ current_demangling_style = gnu_demangling;
+ }
+ else if (strcmp (optarg, "lucid") == 0)
+ {
+ current_demangling_style = lucid_demangling;
+ }
+ else if (strcmp (optarg, "arm") == 0)
+ {
+ current_demangling_style = arm_demangling;
+ }
+ else
+ {
+ fprintf (stderr, "%s: unknown demangling style `%s'\n",
+ program_name, optarg);
+ exit (1);
+ }
+ break;
+ }
+ }
+
+ if (optind < argc)
+ {
+ for ( ; optind < argc; optind++)
+ {
+ demangle_it (argv[optind]);
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ int i = 0;
+ c = getchar ();
+ /* Try to read a label. */
+ while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
+ {
+ if (i >= MBUF_SIZE-1)
+ break;
+ mbuffer[i++] = c;
+ c = getchar ();
+ }
+ if (i > 0)
+ {
+ int skip_first = strip_underscore && i > 1 && mbuffer[0] == '_';
+ mbuffer[i] = 0;
+
+ result = cplus_demangle (mbuffer+skip_first,
+ DMGL_PARAMS | DMGL_ANSI);
+ if (result)
+ {
+ fputs (result, stdout);
+ free (result);
+ }
+ else
+ fputs (mbuffer + skip_first, stdout);
+ }
+ if (c == EOF)
+ break;
+ putchar (c);
+ }
+ }
+
+ exit (0);
+}
+
+#endif /* main */
diff --git a/gnu/usr.bin/gdb/libiberty/fdmatch.c b/gnu/usr.bin/gdb/libiberty/fdmatch.c
new file mode 100644
index 000000000000..0a6de2af0fd0
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/fdmatch.c
@@ -0,0 +1,71 @@
+/* Compare two open file descriptors to see if they refer to the same file.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+
+/*
+
+NAME
+
+ fdmatch -- see if two file descriptors refer to same file
+
+SYNOPSIS
+
+ int fdmatch (int fd1, int fd2)
+
+DESCRIPTION
+
+ Check to see if two open file descriptors refer to the same file.
+ This is useful, for example, when we have an open file descriptor
+ for an unnamed file, and the name of a file that we believe to
+ correspond to that fd. This can happen when we are exec'd with
+ an already open file (stdout for example) or from the SVR4 /proc
+ calls that return open file descriptors for mapped address spaces.
+ All we have to do is open the file by name and check the two file
+ descriptors for a match, which is done by comparing major&minor
+ device numbers and inode numbers.
+
+BUGS
+
+ (FIXME: does this work for networks?)
+ It works for NFS, which assigns a device number to each mount.
+
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int fdmatch (fd1, fd2)
+ int fd1;
+ int fd2;
+{
+ struct stat sbuf1;
+ struct stat sbuf2;
+
+ if ((fstat (fd1, &sbuf1) == 0) &&
+ (fstat (fd2, &sbuf2) == 0) &&
+ (sbuf1.st_dev == sbuf2.st_dev) &&
+ (sbuf1.st_ino == sbuf2.st_ino))
+ {
+ return (1);
+ }
+ else
+ {
+ return (0);
+ }
+}
diff --git a/gnu/usr.bin/gdb/libiberty/getopt.c b/gnu/usr.bin/gdb/libiberty/getopt.c
new file mode 100644
index 000000000000..c7a8b0326418
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/getopt.c
@@ -0,0 +1,750 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License
+ as published by the Free Software Foundation; either version 2, or
+ (at your option) any later version.
+
+ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef __STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#endif /* GNU C library. */
+
+/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
+ long-named option. Because this is not POSIX.2 compliant, it is
+ being phased out. */
+/* #define GETOPT_COMPAT */
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* 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. */
+
+char *optarg = 0;
+
+/* 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. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it.
+ (Supposedly there are some machines where it might get a warning,
+ but changing this conditional to __STDC__ is too risky.) */
+#ifdef __GNUC__
+#ifdef IN_GCC
+#include "gstddef.h"
+#else
+#include <stddef.h>
+#endif
+extern size_t strlen (const char *);
+#endif
+
+#endif /* GNU C library. */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ int option_index;
+
+ optarg = 0;
+
+ /* Initialize the internal data when the first call is made.
+ Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ if (optind == 0)
+ {
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (getenv ("POSIXLY_CORRECT") != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+ }
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Now skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* Special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
+#ifdef GETOPT_COMPAT
+ && (longopts == NULL
+ || argv[optind][0] != '+' || argv[optind][1] == '\0')
+#endif /* GETOPT_COMPAT */
+ )
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Start decoding its characters. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ if (longopts != NULL
+ && ((argv[optind][0] == '-'
+ && (argv[optind][1] == '-' || long_only))
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ ))
+ {
+ const struct option *p;
+ char *s = nextchar;
+ int exact = 0;
+ int ambig = 0;
+ const struct option *pfound = NULL;
+ int indfound;
+
+ while (*s && *s != '=')
+ s++;
+
+ /* Test all options for either exact match or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name;
+ p++, option_index++)
+ if (!strncmp (p->name, nextchar, s - nextchar))
+ {
+ if (s - nextchar == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*s)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = s + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+#ifdef GETOPT_COMPAT
+ || argv[optind][0] == '+'
+#endif /* GETOPT_COMPAT */
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+#if 0
+ if (c < 040 || c >= 0177)
+ fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+ argv[0], c);
+ else
+ fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+#else
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+#endif
+ }
+ optopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = 0;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+#if 0
+ fprintf (stderr, "%s: option `-%c' requires an argument\n",
+ argv[0], c);
+#else
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+#endif
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/gnu/usr.bin/gdb/libiberty/getopt1.c b/gnu/usr.bin/gdb/libiberty/getopt1.c
new file mode 100644
index 000000000000..6806da5f983f
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/getopt1.c
@@ -0,0 +1,180 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License
+ as published by the Free Software Foundation; either version 2, or
+ (at your option) any later version.
+
+ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "getopt.h"
+
+#ifndef __STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#else
+char *getenv ();
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/gnu/usr.bin/gdb/libiberty/ieee-float.c b/gnu/usr.bin/gdb/libiberty/ieee-float.c
new file mode 100644
index 000000000000..b50eb859a1c1
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/ieee-float.c
@@ -0,0 +1,150 @@
+/* IEEE floating point support routines, for GDB, the GNU Debugger.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#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)
+ CONST struct ext_format *ext_format;
+ char *from;
+ double *to;
+{
+ unsigned char *ufrom = (unsigned char *)from;
+ double dto;
+ unsigned long mant0, mant1, exponent;
+
+ memcpy (&mant0, &from[MANBYTE_H], 4);
+ memcpy (&mant1, &from[MANBYTE_L], 4);
+ exponent = ((ufrom[EXPBYTE_H] & (unsigned char)~SIGNMASK) << 8) | ufrom[EXPBYTE_L];
+
+#if 0
+ /* We can't do anything useful with a NaN anyway, so ignore its
+ difference. It will end up as Infinity or something close. */
+ if (exponent == EXT_EXP_NAN) {
+ /* We have a NaN source. */
+ dto = 0.123456789; /* Not much else useful to do -- we don't know if
+ the host system even *has* NaNs, nor how to
+ generate an innocuous one if it does. */
+ } else
+#endif
+ if (exponent == 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, exponent - EXT_EXP_BIAS - 31);
+ dto += ldexp ((double)mant1, exponent - EXT_EXP_BIAS - 31 - 32);
+ if (ufrom[EXPBYTE_H] & SIGNMASK) /* If negative... */
+ dto = -dto; /* ...negate. */
+ }
+ memcpy (to, &dto, sizeof (dto));
+}
+
+/* The converse: convert the double *FROM to an extended float
+ and store where TO points. Neither FROM nor TO have any alignment
+ restrictions. */
+
+void
+double_to_ieee_extended (ext_format, from, to)
+ CONST struct ext_format *ext_format;
+ double *from;
+ char *to;
+{
+ double dfrom;
+ unsigned long twolongs[2];
+ unsigned long mant0, mant1, exponent;
+ unsigned char tobytes[8];
+
+ memcpy (&dfrom, from, sizeof (dfrom));
+ memset (to, 0, 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. */
+ memcpy (twolongs, from, 8);
+ memcpy (tobytes, from, 8);
+#if HOST_BYTE_ORDER == BIG_ENDIAN
+ exponent = ((tobytes[1] & 0xF0) >> 4) | (tobytes[0] & 0x7F) << 4;
+ mant0 = (twolongs[0] << 11) | twolongs[1] >> 21;
+ mant1 = (twolongs[1] << 11);
+#else
+ exponent = ((tobytes[6] & 0xF0) >> 4) | (tobytes[7] & 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 (exponent == 0)
+ mant0 &= 0x7FFFFFFF;
+ else
+ mant0 |= 0x80000000;
+
+ exponent -= DBL_EXP_BIAS; /* Get integer exp */
+ exponent += EXT_EXP_BIAS; /* Offset for extended */
+
+ /* OK, now store it in extended format. */
+ to[EXPBYTE_H] |= (unsigned char)(exponent >> 8); /* Retain sign */
+ to[EXPBYTE_L] = (unsigned char) exponent;
+
+ memcpy (&to[MANBYTE_H], &mant0, 4);
+ memcpy (&to[MANBYTE_L], &mant1, 4);
+}
+
+
+#ifdef IEEE_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() << 16) | (random() & 0xffff);
+ di.i[1] = (random() << 16) | (random() & 0xffff);
+ 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/gnu/usr.bin/gdb/libiberty/ieee-float.h b/gnu/usr.bin/gdb/libiberty/ieee-float.h
new file mode 100644
index 000000000000..68ef23b40fd9
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/ieee-float.h
@@ -0,0 +1,65 @@
+/* IEEE floating point support declarations, for GDB, the GNU Debugger.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+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 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#if !defined (IEEE_FLOAT_H)
+#define IEEE_FLOAT_H 1
+
+#include "ansidecl.h"
+
+/* 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 PARAMS ((const struct ext_format *, char *, double *));
+
+/* The converse: convert the double *FROM to an extended float
+ and store where TO points. */
+
+extern void
+double_to_ieee_extended PARAMS ((const struct ext_format *, double *, char *));
+
+#endif /* defined (IEEE_FLOAT_H) */
diff --git a/gnu/usr.bin/gdb/libiberty/obstack.c b/gnu/usr.bin/gdb/libiberty/obstack.c
new file mode 100644
index 000000000000..4297bbbd51f1
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/obstack.c
@@ -0,0 +1,460 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+ Copyright (C) 1988, 1993 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Library General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+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 Library General Public License for more details.
+
+You should have received a copy of the GNU Library 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"
+
+/* This is just to get __GNU_LIBRARY__ defined. */
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ program understand `configure --with-gnu-libc' and omit the object files,
+ it is simpler to just do this in the source for each such file. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+
+
+#ifdef __STDC__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment. */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT \
+ ((PTR_INT_TYPE) ((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;
+
+/* Define a macro that either calls functions with the traditional malloc/free
+ calling interface, or calls functions with the mmalloc/mfree interface
+ (that adds an extra first argument), based on the state of use_extra_arg.
+ For free, do not use ?:, since some compilers, like the MIPS compilers,
+ do not allow (expr) ? void : void. */
+
+#define CALL_CHUNKFUN(h, size) \
+ (((h) -> use_extra_arg) \
+ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+ : (*(h)->chunkfun) ((size)))
+
+#define CALL_FREEFUN(h, old_chunk) \
+ do { \
+ if ((h) -> use_extra_arg) \
+ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+ else \
+ (*(h)->freefun) ((old_chunk)); \
+ } while (0)
+
+
+/* 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 = (struct _obstack_chunk * (*)()) chunkfun;
+ h->freefun = freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+ h->use_extra_arg = 0;
+
+ chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+ h->next_free = h->object_base = chunk->contents;
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+ /* The initial chunk now contains no empty object. */
+ h->maybe_empty_object = 0;
+}
+
+void
+_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
+ struct obstack *h;
+ int size;
+ int alignment;
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+ POINTER arg;
+{
+ 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 = (struct _obstack_chunk * (*)()) chunkfun;
+ h->freefun = freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+ h->extra_arg = arg;
+ h->use_extra_arg = 1;
+
+ chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+ h->next_free = h->object_base = chunk->contents;
+ h->chunk_limit = chunk->limit
+ = (char *) chunk + h->chunk_size;
+ chunk->prev = 0;
+ /* The initial chunk now contains no empty object. */
+ h->maybe_empty_object = 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. */
+
+void
+_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 = CALL_CHUNKFUN (h, 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];
+
+ /* If the object just copied was the only data in OLD_CHUNK,
+ free that chunk and remove it from the chain.
+ But not if that chunk might contain an empty object. */
+ if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
+ {
+ new_chunk->prev = old_chunk->prev;
+ CALL_FREEFUN (h, old_chunk);
+ }
+
+ h->object_base = new_chunk->contents;
+ h->next_free = h->object_base + obj_size;
+ /* The new chunk certainly contains no empty object yet. */
+ h->maybe_empty_object = 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. */
+
+#ifdef __STDC__
+/* Suppress -Wmissing-prototypes warning. We don't want to declare this in
+ obstack.h because it is just for debugging. */
+int _obstack_allocated_p (struct obstack *h, POINTER obj);
+#endif
+
+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;
+ /* We use >= rather than > since the object cannot be exactly at
+ the beginning of the chunk but might be an empty object exactly
+ at the end of an adjacent 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. */
+
+#undef obstack_free
+
+/* This function has two names with identical definitions.
+ This is the first one, called from non-ANSI code. */
+
+void
+_obstack_free (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;
+ /* 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;
+ CALL_FREEFUN (h, lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ 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 ();
+}
+
+/* This function is used from ANSI code. */
+
+void
+obstack_free (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;
+ /* 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;
+ CALL_FREEFUN (h, lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ 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 ();
+}
+
+#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 */
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/gnu/usr.bin/gdb/libiberty/sigsetmask.c b/gnu/usr.bin/gdb/libiberty/sigsetmask.c
new file mode 100644
index 000000000000..545b12e57b3f
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/sigsetmask.c
@@ -0,0 +1,44 @@
+/* Version of sigsetmask.c
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Written by Steve Chamberlain (sac@cygnus.com).
+ Contributed by Cygnus Support.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Set the current signal mask to the set provided, and return the
+ previous value */
+
+#define _POSIX_SOURCE
+#include <ansidecl.h>
+#include <signal.h>
+
+#ifdef SIG_SETMASK
+int
+DEFUN(sigsetmask,(set),
+ int set)
+{
+ sigset_t new;
+ sigset_t old;
+
+ sigemptyset (&new);
+ if (set != 0) {
+ abort(); /* FIXME, we don't know how to translate old mask to new */
+ }
+ sigprocmask(SIG_SETMASK, &new, &old);
+ return 1; /* FIXME, we always return 1 as old value. */
+}
+#endif
diff --git a/gnu/usr.bin/gdb/libiberty/spaces.c b/gnu/usr.bin/gdb/libiberty/spaces.c
new file mode 100644
index 000000000000..28f07462d372
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/spaces.c
@@ -0,0 +1,67 @@
+/* Allocate memory region filled with spaces.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/*
+
+NAME
+
+ spaces -- return a pointer to a buffer full of spaces
+
+SYNOPSIS
+
+ char *spaces (int count)
+
+DESCRIPTION
+
+ Returns a pointer to a memory region filled with the specified
+ number of spaces and null terminated. The returned pointer is
+ valid until at least the next call.
+
+BUGS
+
+*/
+
+
+char *
+spaces (count)
+ int count;
+{
+ register char *t;
+ static char *buf;
+ static int maxsize;
+ extern char *malloc ();
+ extern void free ();
+
+ if (count > maxsize)
+ {
+ if (buf)
+ {
+ free (buf);
+ }
+ buf = malloc (count + 1);
+ for (t = buf + count ; t != buf ; )
+ {
+ *--t = ' ';
+ }
+ maxsize = count;
+ buf[count] = '\0';
+ }
+ return (buf + maxsize - count);
+}
+
diff --git a/gnu/usr.bin/gdb/libiberty/strerror.c b/gnu/usr.bin/gdb/libiberty/strerror.c
new file mode 100644
index 000000000000..f377311a4f56
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/strerror.c
@@ -0,0 +1,811 @@
+/* Extended support for using errno values.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by Fred Fish. fnf@cygnus.com
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include "config.h"
+
+#ifndef NEED_sys_errlist
+/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
+ might declare sys_errlist in a way that the compiler might consider
+ incompatible with our later declaration, perhaps by using const
+ attributes. So we hide the declaration in errno.h (if any) using a
+ macro. */
+#define sys_errlist sys_errlist__
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef NEED_sys_errlist
+#undef sys_errlist
+#endif
+
+/* Routines imported from standard C runtime libraries. */
+
+#ifdef __STDC__
+#include <stddef.h>
+extern void *malloc (size_t size); /* 4.10.3.3 */
+extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */
+#else /* !__STDC__ */
+#ifndef const
+#define const
+#endif
+extern char *malloc (); /* Standard memory allocater */
+extern char *memset ();
+#endif /* __STDC__ */
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/* Translation table for errno values. See intro(2) in most UNIX systems
+ Programmers Reference Manuals.
+
+ Note that this table is generally only accessed when it is used at runtime
+ to initialize errno name and message tables that are indexed by errno
+ value.
+
+ Not all of these errnos will exist on all systems. This table is the only
+ thing that should have to be updated as new error numbers are introduced.
+ It's sort of ugly, but at least its portable. */
+
+struct error_info
+{
+ int value; /* The numeric value from <errno.h> */
+ char *name; /* The equivalent symbolic value */
+ char *msg; /* Short message about this value */
+};
+
+static const struct error_info error_table[] =
+{
+#if defined (EPERM)
+ {EPERM, "EPERM", "Not owner"},
+#endif
+#if defined (ENOENT)
+ {ENOENT, "ENOENT", "No such file or directory"},
+#endif
+#if defined (ESRCH)
+ {ESRCH, "ESRCH", "No such process"},
+#endif
+#if defined (EINTR)
+ {EINTR, "EINTR", "Interrupted system call"},
+#endif
+#if defined (EIO)
+ {EIO, "EIO", "I/O error"},
+#endif
+#if defined (ENXIO)
+ {ENXIO, "ENXIO", "No such device or address"},
+#endif
+#if defined (E2BIG)
+ {E2BIG, "E2BIG", "Arg list too long"},
+#endif
+#if defined (ENOEXEC)
+ {ENOEXEC, "ENOEXEC", "Exec format error"},
+#endif
+#if defined (EBADF)
+ {EBADF, "EBADF", "Bad file number"},
+#endif
+#if defined (ECHILD)
+ {ECHILD, "ECHILD", "No child processes"},
+#endif
+#if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */
+ {EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"},
+#endif
+#if defined (EAGAIN)
+ {EAGAIN, "EAGAIN", "No more processes"},
+#endif
+#if defined (ENOMEM)
+ {ENOMEM, "ENOMEM", "Not enough space"},
+#endif
+#if defined (EACCES)
+ {EACCES, "EACCES", "Permission denied"},
+#endif
+#if defined (EFAULT)
+ {EFAULT, "EFAULT", "Bad address"},
+#endif
+#if defined (ENOTBLK)
+ {ENOTBLK, "ENOTBLK", "Block device required"},
+#endif
+#if defined (EBUSY)
+ {EBUSY, "EBUSY", "Device busy"},
+#endif
+#if defined (EEXIST)
+ {EEXIST, "EEXIST", "File exists"},
+#endif
+#if defined (EXDEV)
+ {EXDEV, "EXDEV", "Cross-device link"},
+#endif
+#if defined (ENODEV)
+ {ENODEV, "ENODEV", "No such device"},
+#endif
+#if defined (ENOTDIR)
+ {ENOTDIR, "ENOTDIR", "Not a directory"},
+#endif
+#if defined (EISDIR)
+ {EISDIR, "EISDIR", "Is a directory"},
+#endif
+#if defined (EINVAL)
+ {EINVAL, "EINVAL", "Invalid argument"},
+#endif
+#if defined (ENFILE)
+ {ENFILE, "ENFILE", "File table overflow"},
+#endif
+#if defined (EMFILE)
+ {EMFILE, "EMFILE", "Too many open files"},
+#endif
+#if defined (ENOTTY)
+ {ENOTTY, "ENOTTY", "Not a typewriter"},
+#endif
+#if defined (ETXTBSY)
+ {ETXTBSY, "ETXTBSY", "Text file busy"},
+#endif
+#if defined (EFBIG)
+ {EFBIG, "EFBIG", "File too large"},
+#endif
+#if defined (ENOSPC)
+ {ENOSPC, "ENOSPC", "No space left on device"},
+#endif
+#if defined (ESPIPE)
+ {ESPIPE, "ESPIPE", "Illegal seek"},
+#endif
+#if defined (EROFS)
+ {EROFS, "EROFS", "Read-only file system"},
+#endif
+#if defined (EMLINK)
+ {EMLINK, "EMLINK", "Too many links"},
+#endif
+#if defined (EPIPE)
+ {EPIPE, "EPIPE", "Broken pipe"},
+#endif
+#if defined (EDOM)
+ {EDOM, "EDOM", "Math argument out of domain of func"},
+#endif
+#if defined (ERANGE)
+ {ERANGE, "ERANGE", "Math result not representable"},
+#endif
+#if defined (ENOMSG)
+ {ENOMSG, "ENOMSG", "No message of desired type"},
+#endif
+#if defined (EIDRM)
+ {EIDRM, "EIDRM", "Identifier removed"},
+#endif
+#if defined (ECHRNG)
+ {ECHRNG, "ECHRNG", "Channel number out of range"},
+#endif
+#if defined (EL2NSYNC)
+ {EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"},
+#endif
+#if defined (EL3HLT)
+ {EL3HLT, "EL3HLT", "Level 3 halted"},
+#endif
+#if defined (EL3RST)
+ {EL3RST, "EL3RST", "Level 3 reset"},
+#endif
+#if defined (ELNRNG)
+ {ELNRNG, "ELNRNG", "Link number out of range"},
+#endif
+#if defined (EUNATCH)
+ {EUNATCH, "EUNATCH", "Protocol driver not attached"},
+#endif
+#if defined (ENOCSI)
+ {ENOCSI, "ENOCSI", "No CSI structure available"},
+#endif
+#if defined (EL2HLT)
+ {EL2HLT, "EL2HLT", "Level 2 halted"},
+#endif
+#if defined (EDEADLK)
+ {EDEADLK, "EDEADLK", "Deadlock condition"},
+#endif
+#if defined (ENOLCK)
+ {ENOLCK, "ENOLCK", "No record locks available"},
+#endif
+#if defined (EBADE)
+ {EBADE, "EBADE", "Invalid exchange"},
+#endif
+#if defined (EBADR)
+ {EBADR, "EBADR", "Invalid request descriptor"},
+#endif
+#if defined (EXFULL)
+ {EXFULL, "EXFULL", "Exchange full"},
+#endif
+#if defined (ENOANO)
+ {ENOANO, "ENOANO", "No anode"},
+#endif
+#if defined (EBADRQC)
+ {EBADRQC, "EBADRQC", "Invalid request code"},
+#endif
+#if defined (EBADSLT)
+ {EBADSLT, "EBADSLT", "Invalid slot"},
+#endif
+#if defined (EDEADLOCK)
+ {EDEADLOCK, "EDEADLOCK", "File locking deadlock error"},
+#endif
+#if defined (EBFONT)
+ {EBFONT, "EBFONT", "Bad font file format"},
+#endif
+#if defined (ENOSTR)
+ {ENOSTR, "ENOSTR", "Device not a stream"},
+#endif
+#if defined (ENODATA)
+ {ENODATA, "ENODATA", "No data available"},
+#endif
+#if defined (ETIME)
+ {ETIME, "ETIME", "Timer expired"},
+#endif
+#if defined (ENOSR)
+ {ENOSR, "ENOSR", "Out of streams resources"},
+#endif
+#if defined (ENONET)
+ {ENONET, "ENONET", "Machine is not on the network"},
+#endif
+#if defined (ENOPKG)
+ {ENOPKG, "ENOPKG", "Package not installed"},
+#endif
+#if defined (EREMOTE)
+ {EREMOTE, "EREMOTE", "Object is remote"},
+#endif
+#if defined (ENOLINK)
+ {ENOLINK, "ENOLINK", "Link has been severed"},
+#endif
+#if defined (EADV)
+ {EADV, "EADV", "Advertise error"},
+#endif
+#if defined (ESRMNT)
+ {ESRMNT, "ESRMNT", "Srmount error"},
+#endif
+#if defined (ECOMM)
+ {ECOMM, "ECOMM", "Communication error on send"},
+#endif
+#if defined (EPROTO)
+ {EPROTO, "EPROTO", "Protocol error"},
+#endif
+#if defined (EMULTIHOP)
+ {EMULTIHOP, "EMULTIHOP", "Multihop attempted"},
+#endif
+#if defined (EDOTDOT)
+ {EDOTDOT, "EDOTDOT", "RFS specific error"},
+#endif
+#if defined (EBADMSG)
+ {EBADMSG, "EBADMSG", "Not a data message"},
+#endif
+#if defined (ENAMETOOLONG)
+ {ENAMETOOLONG, "ENAMETOOLONG", "File name too long"},
+#endif
+#if defined (EOVERFLOW)
+ {EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"},
+#endif
+#if defined (ENOTUNIQ)
+ {ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"},
+#endif
+#if defined (EBADFD)
+ {EBADFD, "EBADFD", "File descriptor in bad state"},
+#endif
+#if defined (EREMCHG)
+ {EREMCHG, "EREMCHG", "Remote address changed"},
+#endif
+#if defined (ELIBACC)
+ {ELIBACC, "ELIBACC", "Can not access a needed shared library"},
+#endif
+#if defined (ELIBBAD)
+ {ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"},
+#endif
+#if defined (ELIBSCN)
+ {ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"},
+#endif
+#if defined (ELIBMAX)
+ {ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"},
+#endif
+#if defined (ELIBEXEC)
+ {ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"},
+#endif
+#if defined (EILSEQ)
+ {EILSEQ, "EILSEQ", "Illegal byte sequence"},
+#endif
+#if defined (ENOSYS)
+ {ENOSYS, "ENOSYS", "Operation not applicable"},
+#endif
+#if defined (ELOOP)
+ {ELOOP, "ELOOP", "Too many symbolic links encountered"},
+#endif
+#if defined (ERESTART)
+ {ERESTART, "ERESTART", "Interrupted system call should be restarted"},
+#endif
+#if defined (ESTRPIPE)
+ {ESTRPIPE, "ESTRPIPE", "Streams pipe error"},
+#endif
+#if defined (ENOTEMPTY)
+ {ENOTEMPTY, "ENOTEMPTY", "Directory not empty"},
+#endif
+#if defined (EUSERS)
+ {EUSERS, "EUSERS", "Too many users"},
+#endif
+#if defined (ENOTSOCK)
+ {ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"},
+#endif
+#if defined (EDESTADDRREQ)
+ {EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"},
+#endif
+#if defined (EMSGSIZE)
+ {EMSGSIZE, "EMSGSIZE", "Message too long"},
+#endif
+#if defined (EPROTOTYPE)
+ {EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"},
+#endif
+#if defined (ENOPROTOOPT)
+ {ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"},
+#endif
+#if defined (EPROTONOSUPPORT)
+ {EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"},
+#endif
+#if defined (ESOCKTNOSUPPORT)
+ {ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"},
+#endif
+#if defined (EOPNOTSUPP)
+ {EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"},
+#endif
+#if defined (EPFNOSUPPORT)
+ {EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"},
+#endif
+#if defined (EAFNOSUPPORT)
+ {EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"},
+#endif
+#if defined (EADDRINUSE)
+ {EADDRINUSE, "EADDRINUSE", "Address already in use"},
+#endif
+#if defined (EADDRNOTAVAIL)
+ {EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"},
+#endif
+#if defined (ENETDOWN)
+ {ENETDOWN, "ENETDOWN", "Network is down"},
+#endif
+#if defined (ENETUNREACH)
+ {ENETUNREACH, "ENETUNREACH", "Network is unreachable"},
+#endif
+#if defined (ENETRESET)
+ {ENETRESET, "ENETRESET", "Network dropped connection because of reset"},
+#endif
+#if defined (ECONNABORTED)
+ {ECONNABORTED, "ECONNABORTED", "Software caused connection abort"},
+#endif
+#if defined (ECONNRESET)
+ {ECONNRESET, "ECONNRESET", "Connection reset by peer"},
+#endif
+#if defined (ENOBUFS)
+ {ENOBUFS, "ENOBUFS", "No buffer space available"},
+#endif
+#if defined (EISCONN)
+ {EISCONN, "EISCONN", "Transport endpoint is already connected"},
+#endif
+#if defined (ENOTCONN)
+ {ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"},
+#endif
+#if defined (ESHUTDOWN)
+ {ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"},
+#endif
+#if defined (ETOOMANYREFS)
+ {ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"},
+#endif
+#if defined (ETIMEDOUT)
+ {ETIMEDOUT, "ETIMEDOUT", "Connection timed out"},
+#endif
+#if defined (ECONNREFUSED)
+ {ECONNREFUSED, "ECONNREFUSED", "Connection refused"},
+#endif
+#if defined (EHOSTDOWN)
+ {EHOSTDOWN, "EHOSTDOWN", "Host is down"},
+#endif
+#if defined (EHOSTUNREACH)
+ {EHOSTUNREACH, "EHOSTUNREACH", "No route to host"},
+#endif
+#if defined (EALREADY)
+ {EALREADY, "EALREADY", "Operation already in progress"},
+#endif
+#if defined (EINPROGRESS)
+ {EINPROGRESS, "EINPROGRESS", "Operation now in progress"},
+#endif
+#if defined (ESTALE)
+ {ESTALE, "ESTALE", "Stale NFS file handle"},
+#endif
+#if defined (EUCLEAN)
+ {EUCLEAN, "EUCLEAN", "Structure needs cleaning"},
+#endif
+#if defined (ENOTNAM)
+ {ENOTNAM, "ENOTNAM", "Not a XENIX named type file"},
+#endif
+#if defined (ENAVAIL)
+ {ENAVAIL, "ENAVAIL", "No XENIX semaphores available"},
+#endif
+#if defined (EISNAM)
+ {EISNAM, "EISNAM", "Is a named type file"},
+#endif
+#if defined (EREMOTEIO)
+ {EREMOTEIO, "EREMOTEIO", "Remote I/O error"},
+#endif
+ {0, NULL, NULL}
+};
+
+/* Translation table allocated and initialized at runtime. Indexed by the
+ errno value to find the equivalent symbolic value. */
+
+static char **error_names;
+static int num_error_names = 0;
+
+/* Translation table allocated and initialized at runtime, if it does not
+ already exist in the host environment. Indexed by the errno value to find
+ the descriptive string.
+
+ We don't export it for use in other modules because even though it has the
+ same name, it differs from other implementations in that it is dynamically
+ initialized rather than statically initialized. */
+
+#ifdef NEED_sys_errlist
+
+static int sys_nerr;
+static char **sys_errlist;
+
+#else
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+#endif
+
+
+/*
+
+NAME
+
+ init_error_tables -- initialize the name and message tables
+
+SYNOPSIS
+
+ static void init_error_tables ();
+
+DESCRIPTION
+
+ Using the error_table, which is initialized at compile time, generate
+ the error_names and the sys_errlist (if needed) tables, which are
+ indexed at runtime by a specific errno value.
+
+BUGS
+
+ The initialization of the tables may fail under low memory conditions,
+ in which case we don't do anything particularly useful, but we don't
+ bomb either. Who knows, it might succeed at a later point if we free
+ some memory in the meantime. In any case, the other routines know
+ how to deal with lack of a table after trying to initialize it. This
+ may or may not be considered to be a bug, that we don't specifically
+ warn about this particular failure mode.
+
+*/
+
+static void
+init_error_tables ()
+{
+ const struct error_info *eip;
+ int nbytes;
+
+ /* If we haven't already scanned the error_table once to find the maximum
+ errno value, then go find it now. */
+
+ if (num_error_names == 0)
+ {
+ for (eip = error_table; eip -> name != NULL; eip++)
+ {
+ if (eip -> value >= num_error_names)
+ {
+ num_error_names = eip -> value + 1;
+ }
+ }
+ }
+
+ /* Now attempt to allocate the error_names table, zero it out, and then
+ initialize it from the statically initialized error_table. */
+
+ if (error_names == NULL)
+ {
+ nbytes = num_error_names * sizeof (char *);
+ if ((error_names = (char **) malloc (nbytes)) != NULL)
+ {
+ memset (error_names, 0, nbytes);
+ for (eip = error_table; eip -> name != NULL; eip++)
+ {
+ error_names[eip -> value] = eip -> name;
+ }
+ }
+ }
+
+#ifdef NEED_sys_errlist
+
+ /* Now attempt to allocate the sys_errlist table, zero it out, and then
+ initialize it from the statically initialized error_table. */
+
+ if (sys_errlist == NULL)
+ {
+ nbytes = num_error_names * sizeof (char *);
+ if ((sys_errlist = (char **) malloc (nbytes)) != NULL)
+ {
+ memset (sys_errlist, 0, nbytes);
+ sys_nerr = num_error_names;
+ for (eip = error_table; eip -> name != NULL; eip++)
+ {
+ sys_errlist[eip -> value] = eip -> msg;
+ }
+ }
+ }
+
+#endif
+
+}
+
+/*
+
+NAME
+
+ errno_max -- return the max errno value
+
+SYNOPSIS
+
+ int errno_max ();
+
+DESCRIPTION
+
+ Returns the maximum errno value for which a corresponding symbolic
+ name or message is available. Note that in the case where
+ we use the sys_errlist supplied by the system, it is possible for
+ there to be more symbolic names than messages, or vice versa.
+ In fact, the manual page for perror(3C) explicitly warns that one
+ should check the size of the table (sys_nerr) before indexing it,
+ since new error codes may be added to the system before they are
+ added to the table. Thus sys_nerr might be smaller than value
+ implied by the largest errno value defined in <errno.h>.
+
+ We return the maximum value that can be used to obtain a meaningful
+ symbolic name or message.
+
+*/
+
+int
+errno_max ()
+{
+ int maxsize;
+
+ if (error_names == NULL)
+ {
+ init_error_tables ();
+ }
+ maxsize = MAX (sys_nerr, num_error_names);
+ return (maxsize - 1);
+}
+
+#ifdef NEED_strerror
+
+/*
+
+NAME
+
+ strerror -- map an error number to an error message string
+
+SYNOPSIS
+
+ char *strerror (int errnoval)
+
+DESCRIPTION
+
+ Maps an errno number to an error message string, the contents of
+ which are implementation defined. On systems which have the external
+ variables sys_nerr and sys_errlist, these strings will be the same
+ as the ones used by perror().
+
+ If the supplied error number is within the valid range of indices
+ for the sys_errlist, but no message is available for the particular
+ error number, then returns the string "Error NUM", where NUM is the
+ error number.
+
+ If the supplied error number is not a valid index into sys_errlist,
+ returns NULL.
+
+ The returned string is only guaranteed to be valid only until the
+ next call to strerror.
+
+*/
+
+char *
+strerror (errnoval)
+ int errnoval;
+{
+ char *msg;
+ static char buf[32];
+
+#ifdef NEED_sys_errlist
+
+ if (error_names == NULL)
+ {
+ init_error_tables ();
+ }
+
+#endif
+
+ if ((errnoval < 0) || (errnoval >= sys_nerr))
+ {
+ /* Out of range, just return NULL */
+ msg = NULL;
+ }
+ else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
+ {
+ /* In range, but no sys_errlist or no entry at this index. */
+ sprintf (buf, "Error %d", errnoval);
+ msg = buf;
+ }
+ else
+ {
+ /* In range, and a valid message. Just return the message. */
+ msg = sys_errlist[errnoval];
+ }
+
+ return (msg);
+}
+
+#endif /* NEED_strerror */
+
+
+/*
+
+NAME
+
+ strerrno -- map an error number to a symbolic name string
+
+SYNOPSIS
+
+ char *strerrno (int errnoval)
+
+DESCRIPTION
+
+ Given an error number returned from a system call (typically
+ returned in errno), returns a pointer to a string containing the
+ symbolic name of that error number, as found in <errno.h>.
+
+ If the supplied error number is within the valid range of indices
+ for symbolic names, but no name is available for the particular
+ error number, then returns the string "Error NUM", where NUM is
+ the error number.
+
+ If the supplied error number is not within the range of valid
+ indices, then returns NULL.
+
+BUGS
+
+ The contents of the location pointed to are only guaranteed to be
+ valid until the next call to strerrno.
+
+*/
+
+char *
+strerrno (errnoval)
+ int errnoval;
+{
+ char *name;
+ static char buf[32];
+
+ if (error_names == NULL)
+ {
+ init_error_tables ();
+ }
+
+ if ((errnoval < 0) || (errnoval >= num_error_names))
+ {
+ /* Out of range, just return NULL */
+ name = NULL;
+ }
+ else if ((error_names == NULL) || (error_names[errnoval] == NULL))
+ {
+ /* In range, but no error_names or no entry at this index. */
+ sprintf (buf, "Error %d", errnoval);
+ name = buf;
+ }
+ else
+ {
+ /* In range, and a valid name. Just return the name. */
+ name = error_names[errnoval];
+ }
+
+ return (name);
+}
+
+/*
+
+NAME
+
+ strtoerrno -- map a symbolic errno name to a numeric value
+
+SYNOPSIS
+
+ int strtoerrno (char *name)
+
+DESCRIPTION
+
+ Given the symbolic name of a error number, map it to an errno value.
+ If no translation is found, returns 0.
+
+*/
+
+int
+strtoerrno (name)
+ char *name;
+{
+ int errnoval = 0;
+
+ if (name != NULL)
+ {
+ if (error_names == NULL)
+ {
+ init_error_tables ();
+ }
+ for (errnoval = 0; errnoval < num_error_names; errnoval++)
+ {
+ if ((error_names[errnoval] != NULL) &&
+ (strcmp (name, error_names[errnoval]) == 0))
+ {
+ break;
+ }
+ }
+ if (errnoval == num_error_names)
+ {
+ errnoval = 0;
+ }
+ }
+ return (errnoval);
+}
+
+
+/* A simple little main that does nothing but print all the errno translations
+ if MAIN is defined and this file is compiled and linked. */
+
+#ifdef MAIN
+
+main ()
+{
+ int errn;
+ int errnmax;
+ char *name;
+ char *msg;
+ char *strerrno ();
+ char *strerror ();
+
+ errnmax = errno_max ();
+ printf ("%d entries in names table.\n", num_error_names);
+ printf ("%d entries in messages table.\n", sys_nerr);
+ printf ("%d is max useful index.\n", errnmax);
+
+ /* Keep printing values until we get to the end of *both* tables, not
+ *either* table. Note that knowing the maximum useful index does *not*
+ relieve us of the responsibility of testing the return pointer for
+ NULL. */
+
+ for (errn = 0; errn <= errnmax; errn++)
+ {
+ name = strerrno (errn);
+ name = (name == NULL) ? "<NULL>" : name;
+ msg = strerror (errn);
+ msg = (msg == NULL) ? "<NULL>" : msg;
+ printf ("%-4d%-18s%s\n", errn, name, msg);
+ }
+}
+
+#endif
diff --git a/gnu/usr.bin/gdb/libiberty/strsignal.c b/gnu/usr.bin/gdb/libiberty/strsignal.c
new file mode 100644
index 000000000000..15411ff496c6
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/strsignal.c
@@ -0,0 +1,634 @@
+/* Extended support for using signal values.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by Fred Fish. fnf@cygnus.com
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+
+#include "config.h"
+
+#ifdef LOSING_SYS_SIGLIST
+#define sys_siglist no_such_symbol
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+
+/* Routines imported from standard C runtime libraries. */
+
+#ifdef __STDC__
+#include <stddef.h>
+extern void *malloc (size_t size); /* 4.10.3.3 */
+extern void *memset (void *s, int c, size_t n); /* 4.11.6.1 */
+#else /* !__STDC__ */
+#ifndef const
+#define const
+#endif
+extern char *malloc (); /* Standard memory allocater */
+extern char *memset ();
+#endif /* __STDC__ */
+
+#ifdef LOSING_SYS_SIGLIST
+#undef sys_siglist
+#endif
+
+
+#ifndef NULL
+# ifdef __STDC__
+# define NULL (void *) 0
+# else
+# define NULL 0
+# endif
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/* Translation table for signal values.
+
+ Note that this table is generally only accessed when it is used at runtime
+ to initialize signal name and message tables that are indexed by signal
+ value.
+
+ Not all of these signals will exist on all systems. This table is the only
+ thing that should have to be updated as new signal numbers are introduced.
+ It's sort of ugly, but at least its portable. */
+
+struct signal_info
+{
+ int value; /* The numeric value from <signal.h> */
+ char *name; /* The equivalent symbolic value */
+ char *msg; /* Short message about this value */
+};
+
+static const struct signal_info signal_table[] =
+{
+#if defined (SIGHUP)
+ {SIGHUP, "SIGHUP", "Hangup"},
+#endif
+#if defined (SIGINT)
+ {SIGINT, "SIGINT", "Interrupt"},
+#endif
+#if defined (SIGQUIT)
+ {SIGQUIT, "SIGQUIT", "Quit"},
+#endif
+#if defined (SIGILL)
+ {SIGILL, "SIGILL", "Illegal instruction"},
+#endif
+#if defined (SIGTRAP)
+ {SIGTRAP, "SIGTRAP", "Trace/breakpoint trap"},
+#endif
+/* Put SIGIOT before SIGABRT, so that if SIGIOT==SIGABRT then SIGABRT
+ overrides SIGIOT. SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. */
+#if defined (SIGIOT)
+ {SIGIOT, "SIGIOT", "IOT trap"},
+#endif
+#if defined (SIGABRT)
+ {SIGABRT, "SIGABRT", "Aborted"},
+#endif
+#if defined (SIGEMT)
+ {SIGEMT, "SIGEMT", "Emulation trap"},
+#endif
+#if defined (SIGFPE)
+ {SIGFPE, "SIGFPE", "Arithmetic exception"},
+#endif
+#if defined (SIGKILL)
+ {SIGKILL, "SIGKILL", "Killed"},
+#endif
+#if defined (SIGBUS)
+ {SIGBUS, "SIGBUS", "Bus error"},
+#endif
+#if defined (SIGSEGV)
+ {SIGSEGV, "SIGSEGV", "Segmentation fault"},
+#endif
+#if defined (SIGSYS)
+ {SIGSYS, "SIGSYS", "Bad system call"},
+#endif
+#if defined (SIGPIPE)
+ {SIGPIPE, "SIGPIPE", "Broken pipe"},
+#endif
+#if defined (SIGALRM)
+ {SIGALRM, "SIGALRM", "Alarm clock"},
+#endif
+#if defined (SIGTERM)
+ {SIGTERM, "SIGTERM", "Terminated"},
+#endif
+#if defined (SIGUSR1)
+ {SIGUSR1, "SIGUSR1", "User defined signal 1"},
+#endif
+#if defined (SIGUSR2)
+ {SIGUSR2, "SIGUSR2", "User defined signal 2"},
+#endif
+/* Put SIGCLD before SIGCHLD, so that if SIGCLD==SIGCHLD then SIGCHLD
+ overrides SIGCLD. SIGCHLD is in POXIX.1 */
+#if defined (SIGCLD)
+ {SIGCLD, "SIGCLD", "Child status changed"},
+#endif
+#if defined (SIGCHLD)
+ {SIGCHLD, "SIGCHLD", "Child status changed"},
+#endif
+#if defined (SIGPWR)
+ {SIGPWR, "SIGPWR", "Power fail/restart"},
+#endif
+#if defined (SIGWINCH)
+ {SIGWINCH, "SIGWINCH", "Window size changed"},
+#endif
+#if defined (SIGURG)
+ {SIGURG, "SIGURG", "Urgent I/O condition"},
+#endif
+#if defined (SIGIO)
+ /* "I/O pending" has also been suggested, but is misleading since the
+ signal only happens when the process has asked for it, not everytime
+ I/O is pending. */
+ {SIGIO, "SIGIO", "I/O possible"},
+#endif
+#if defined (SIGPOLL)
+ {SIGPOLL, "SIGPOLL", "Pollable event occurred"},
+#endif
+#if defined (SIGSTOP)
+ {SIGSTOP, "SIGSTOP", "Stopped (signal)"},
+#endif
+#if defined (SIGTSTP)
+ {SIGTSTP, "SIGTSTP", "Stopped (user)"},
+#endif
+#if defined (SIGCONT)
+ {SIGCONT, "SIGCONT", "Continued"},
+#endif
+#if defined (SIGTTIN)
+ {SIGTTIN, "SIGTTIN", "Stopped (tty input)"},
+#endif
+#if defined (SIGTTOU)
+ {SIGTTOU, "SIGTTOU", "Stopped (tty output)"},
+#endif
+#if defined (SIGVTALRM)
+ {SIGVTALRM, "SIGVTALRM", "Virtual timer expired"},
+#endif
+#if defined (SIGPROF)
+ {SIGPROF, "SIGPROF", "Profiling timer expired"},
+#endif
+#if defined (SIGXCPU)
+ {SIGXCPU, "SIGXCPU", "CPU time limit exceeded"},
+#endif
+#if defined (SIGXFSZ)
+ {SIGXFSZ, "SIGXFSZ", "File size limit exceeded"},
+#endif
+#if defined (SIGWIND)
+ {SIGWIND, "SIGWIND", "SIGWIND"},
+#endif
+#if defined (SIGPHONE)
+ {SIGPHONE, "SIGPHONE", "SIGPHONE"},
+#endif
+#if defined (SIGLOST)
+ {SIGLOST, "SIGLOST", "Resource lost"},
+#endif
+#if defined (SIGWAITING)
+ {SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"},
+#endif
+#if defined (SIGLWP)
+ {SIGLWP, "SIGLWP", "Signal LWP"},
+#endif
+#if defined (SIGDANGER)
+ {SIGDANGER, "SIGDANGER", "Swap space dangerously low"},
+#endif
+#if defined (SIGGRANT)
+ {SIGGRANT, "SIGGRANT", "Monitor mode granted"},
+#endif
+#if defined (SIGRETRACT)
+ {SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"},
+#endif
+#if defined (SIGMSG)
+ {SIGMSG, "SIGMSG", "Monitor mode data available"},
+#endif
+#if defined (SIGSOUND)
+ {SIGSOUND, "SIGSOUND", "Sound completed"},
+#endif
+#if defined (SIGSAK)
+ {SIGSAK, "SIGSAK", "Secure attention"},
+#endif
+ {0, NULL, NULL}
+};
+
+/* Translation table allocated and initialized at runtime. Indexed by the
+ signal value to find the equivalent symbolic value. */
+
+static char **signal_names;
+static int num_signal_names = 0;
+
+/* Translation table allocated and initialized at runtime, if it does not
+ already exist in the host environment. Indexed by the signal value to find
+ the descriptive string.
+
+ We don't export it for use in other modules because even though it has the
+ same name, it differs from other implementations in that it is dynamically
+ initialized rather than statically initialized. */
+
+#ifdef NEED_sys_siglist
+
+static int sys_nsig;
+static char **sys_siglist;
+
+#else
+
+static int sys_nsig = NSIG;
+extern const char * const sys_siglist[];
+
+#endif
+
+
+/*
+
+NAME
+
+ init_signal_tables -- initialize the name and message tables
+
+SYNOPSIS
+
+ static void init_signal_tables ();
+
+DESCRIPTION
+
+ Using the signal_table, which is initialized at compile time, generate
+ the signal_names and the sys_siglist (if needed) tables, which are
+ indexed at runtime by a specific signal value.
+
+BUGS
+
+ The initialization of the tables may fail under low memory conditions,
+ in which case we don't do anything particularly useful, but we don't
+ bomb either. Who knows, it might succeed at a later point if we free
+ some memory in the meantime. In any case, the other routines know
+ how to deal with lack of a table after trying to initialize it. This
+ may or may not be considered to be a bug, that we don't specifically
+ warn about this particular failure mode.
+
+*/
+
+static void
+init_signal_tables ()
+{
+ const struct signal_info *eip;
+ int nbytes;
+
+ /* If we haven't already scanned the signal_table once to find the maximum
+ signal value, then go find it now. */
+
+ if (num_signal_names == 0)
+ {
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ if (eip -> value >= num_signal_names)
+ {
+ num_signal_names = eip -> value + 1;
+ }
+ }
+ }
+
+ /* Now attempt to allocate the signal_names table, zero it out, and then
+ initialize it from the statically initialized signal_table. */
+
+ if (signal_names == NULL)
+ {
+ nbytes = num_signal_names * sizeof (char *);
+ if ((signal_names = (char **) malloc (nbytes)) != NULL)
+ {
+ memset (signal_names, 0, nbytes);
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ signal_names[eip -> value] = eip -> name;
+ }
+ }
+ }
+
+#ifdef NEED_sys_siglist
+
+ /* Now attempt to allocate the sys_siglist table, zero it out, and then
+ initialize it from the statically initialized signal_table. */
+
+ if (sys_siglist == NULL)
+ {
+ nbytes = num_signal_names * sizeof (char *);
+ if ((sys_siglist = (char **) malloc (nbytes)) != NULL)
+ {
+ memset (sys_siglist, 0, nbytes);
+ sys_nsig = num_signal_names;
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ sys_siglist[eip -> value] = eip -> msg;
+ }
+ }
+ }
+
+#endif
+
+}
+
+
+/*
+
+NAME
+
+ signo_max -- return the max signo value
+
+SYNOPSIS
+
+ int signo_max ();
+
+DESCRIPTION
+
+ Returns the maximum signo value for which a corresponding symbolic
+ name or message is available. Note that in the case where
+ we use the sys_siglist supplied by the system, it is possible for
+ there to be more symbolic names than messages, or vice versa.
+ In fact, the manual page for psignal(3b) explicitly warns that one
+ should check the size of the table (NSIG) before indexing it,
+ since new signal codes may be added to the system before they are
+ added to the table. Thus NSIG might be smaller than value
+ implied by the largest signo value defined in <signal.h>.
+
+ We return the maximum value that can be used to obtain a meaningful
+ symbolic name or message.
+
+*/
+
+int
+signo_max ()
+{
+ int maxsize;
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ maxsize = MAX (sys_nsig, num_signal_names);
+ return (maxsize - 1);
+}
+
+
+/*
+
+NAME
+
+ strsignal -- map a signal number to a signal message string
+
+SYNOPSIS
+
+ char *strsignal (int signo)
+
+DESCRIPTION
+
+ Maps an signal number to an signal message string, the contents of
+ which are implementation defined. On systems which have the external
+ variable sys_siglist, these strings will be the same as the ones used
+ by psignal().
+
+ If the supplied signal number is within the valid range of indices
+ for the sys_siglist, but no message is available for the particular
+ signal number, then returns the string "Signal NUM", where NUM is the
+ signal number.
+
+ If the supplied signal number is not a valid index into sys_siglist,
+ returns NULL.
+
+ The returned string is only guaranteed to be valid only until the
+ next call to strsignal.
+
+*/
+
+char *
+strsignal (signo)
+ int signo;
+{
+ char *msg;
+ static char buf[32];
+
+#ifdef NEED_sys_siglist
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+
+#endif
+
+ if ((signo < 0) || (signo >= sys_nsig))
+ {
+ /* Out of range, just return NULL */
+ msg = NULL;
+ }
+ else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL))
+ {
+ /* In range, but no sys_siglist or no entry at this index. */
+ sprintf (buf, "Signal %d", signo);
+ msg = buf;
+ }
+ else
+ {
+ /* In range, and a valid message. Just return the message. */
+ msg = (char*)sys_siglist[signo];
+ }
+
+ return (msg);
+}
+
+
+/*
+
+NAME
+
+ strsigno -- map an signal number to a symbolic name string
+
+SYNOPSIS
+
+ char *strsigno (int signo)
+
+DESCRIPTION
+
+ Given an signal number, returns a pointer to a string containing
+ the symbolic name of that signal number, as found in <signal.h>.
+
+ If the supplied signal number is within the valid range of indices
+ for symbolic names, but no name is available for the particular
+ signal number, then returns the string "Signal NUM", where NUM is
+ the signal number.
+
+ If the supplied signal number is not within the range of valid
+ indices, then returns NULL.
+
+BUGS
+
+ The contents of the location pointed to are only guaranteed to be
+ valid until the next call to strsigno.
+
+*/
+
+char *
+strsigno (signo)
+ int signo;
+{
+ char *name;
+ static char buf[32];
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+
+ if ((signo < 0) || (signo >= num_signal_names))
+ {
+ /* Out of range, just return NULL */
+ name = NULL;
+ }
+ else if ((signal_names == NULL) || (signal_names[signo] == NULL))
+ {
+ /* In range, but no signal_names or no entry at this index. */
+ sprintf (buf, "Signal %d", signo);
+ name = buf;
+ }
+ else
+ {
+ /* In range, and a valid name. Just return the name. */
+ name = signal_names[signo];
+ }
+
+ return (name);
+}
+
+
+/*
+
+NAME
+
+ strtosigno -- map a symbolic signal name to a numeric value
+
+SYNOPSIS
+
+ int strtosigno (char *name)
+
+DESCRIPTION
+
+ Given the symbolic name of a signal, map it to a signal number.
+ If no translation is found, returns 0.
+
+*/
+
+int
+strtosigno (name)
+ char *name;
+{
+ int signo = 0;
+
+ if (name != NULL)
+ {
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ for (signo = 0; signo < num_signal_names; signo++)
+ {
+ if ((signal_names[signo] != NULL) &&
+ (strcmp (name, signal_names[signo]) == 0))
+ {
+ break;
+ }
+ }
+ if (signo == num_signal_names)
+ {
+ signo = 0;
+ }
+ }
+ return (signo);
+}
+
+
+/*
+
+NAME
+
+ psignal -- print message about signal to stderr
+
+SYNOPSIS
+
+ void psignal (unsigned signo, char *message);
+
+DESCRIPTION
+
+ Print to the standard error the message, followed by a colon,
+ followed by the description of the signal specified by signo,
+ followed by a newline.
+*/
+
+#ifdef NEED_psignal
+
+void
+psignal (signo, message)
+ unsigned signo;
+ char *message;
+{
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ if ((signo <= 0) || (signo >= sys_nsig))
+ {
+ fprintf (stderr, "%s: unknown signal\n", message);
+ }
+ else
+ {
+ fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]);
+ }
+}
+
+#endif /* NEED_psignal */
+
+
+/* A simple little main that does nothing but print all the signal translations
+ if MAIN is defined and this file is compiled and linked. */
+
+#ifdef MAIN
+
+main ()
+{
+ int signo;
+ int maxsigno;
+ char *name;
+ char *msg;
+ char *strsigno ();
+ char *strsignal ();
+
+ maxsigno = signo_max ();
+ printf ("%d entries in names table.\n", num_signal_names);
+ printf ("%d entries in messages table.\n", sys_nsig);
+ printf ("%d is max useful index.\n", maxsigno);
+
+ /* Keep printing values until we get to the end of *both* tables, not
+ *either* table. Note that knowing the maximum useful index does *not*
+ relieve us of the responsibility of testing the return pointer for
+ NULL. */
+
+ for (signo = 0; signo <= maxsigno; signo++)
+ {
+ name = strsigno (signo);
+ name = (name == NULL) ? "<NULL>" : name;
+ msg = strsignal (signo);
+ msg = (msg == NULL) ? "<NULL>" : msg;
+ printf ("%-4d%-18s%s\n", signo, name, msg);
+ }
+}
+
+#endif
diff --git a/gnu/usr.bin/gdb/libiberty/xmalloc.c b/gnu/usr.bin/gdb/libiberty/xmalloc.c
new file mode 100644
index 000000000000..be0c7aa9319c
--- /dev/null
+++ b/gnu/usr.bin/gdb/libiberty/xmalloc.c
@@ -0,0 +1,58 @@
+/* memory allocation routines with error checking.
+ Copyright 1989, 1991, 1993 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+
+PTR
+xmalloc (size)
+ size_t size;
+{
+ char * newmem;
+
+ if ((newmem = (char *) malloc ((int) size)) == NULL)
+ {
+ fprintf (stderr, "\nCan't allocate %u bytes\n", size);
+ exit (1);
+ }
+ return (newmem);
+}
+
+PTR
+xrealloc (oldmem, size)
+ PTR oldmem;
+ size_t size;
+{
+ char * newmem;
+
+ if ((newmem = (char *) realloc ((char *) oldmem, (int) size)) == NULL)
+ {
+ fprintf (stderr, "\nCan't reallocate %u bytes\n", size);
+ exit (1);
+ }
+ return (newmem);
+}
diff --git a/gnu/usr.bin/gdb/main.c b/gnu/usr.bin/gdb/main.c
deleted file mode 100644
index 323de87975ad..000000000000
--- a/gnu/usr.bin/gdb/main.c
+++ /dev/null
@@ -1,2241 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)main.c 6.6 (Berkeley) 5/13/91";
-#endif /* not lint */
-
-/* Top level for GDB, the GNU debugger.
- 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 "defs.h"
-#include "command.h"
-#include "param.h"
-#include "expression.h"
-
-#ifdef USG
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-#include <sys/file.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <ctype.h>
-
-#ifdef SET_STACK_LIMIT_HUGE
-#include <sys/time.h>
-#include <sys/resource.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
-
-extern void free ();
-
-/* Version number of GDB, as a string. */
-
-extern char *version;
-
-/*
- * Declare 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 \"set history\". */
-
-struct cmd_list_element *sethistlist;
-
-/* 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];
-
-#ifdef KERNELDEBUG
-/* Nonzero if we're debugging /dev/mem or a kernel crash dump */
-
-int kernel_debugging;
-#endif
-
-/* Nonzero to inhibit confirmation of quitting or restarting
- a stopped inferior. */
-int inhibit_confirm;
-
-/* Nonzero if we can write in text or core file */
-
-int writeable_text;
-
-/* The number of lines on a page, and the number of spaces
- in a line. */
-int linesize, pagesize;
-
-/* Nonzero if we should refrain from using an X window. */
-
-int inhibit_windows = 0;
-
-/* 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 xgdb_verbose;
-
-void execute_command();
-void free_command_lines ();
-char *gdb_readline ();
-char *command_line_input ();
-static void initialize_main ();
-static void initialize_cmd_lists ();
-void command_loop ();
-static void source_command ();
-static void print_gdb_version ();
-static void float_handler ();
-static void cd_command ();
-
-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;
-
-
-/* This is how `error' returns to command level. */
-
-jmp_buf to_top_level;
-
-void
-return_to_top_level ()
-{
- quit_flag = 0;
- immediate_quit = 0;
- clear_breakpoint_commands ();
- clear_momentary_breakpoints ();
- disable_current_display ();
- do_cleanups (0);
- longjmp (to_top_level, 1);
-}
-
-/* Call FUNC with arg ARG, 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, arg, errstring)
- int (*func) ();
- int arg;
- 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) (arg);
- else
- {
- 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);
-}
-
-/* Clean up on error during a "source" command (or execution of a
- user-defined command).
- Close the file opened by the command
- and restore the previous input stream. */
-
-static void
-source_cleanup (stream)
- FILE *stream;
-{
- /* Instream may be 0; set to it when executing user-defined command. */
- if (instream)
- fclose (instream);
- instream = stream;
-}
-
-/*
- * Source $HOME/.gdbinit and $cwd/.gdbinit.
- * If X is enabled, also $HOME/.xgdbinit and $cwd/.xgdbinit.source
- */
-void
-source_init_files()
-{
- char *homedir, initfile[256];
- int samedir = 0;
-
- /* Read init file, if it exists in home directory */
- homedir = getenv ("HOME");
- if (homedir) {
- struct stat homebuf, cwdbuf;
-
- sprintf(initfile, "%s/.gdbinit", homedir);
- if (access (initfile, R_OK) == 0)
- if (!setjmp (to_top_level))
- source_command (initfile);
- if (!inhibit_windows) {
- sprintf(initfile, "%s/.xgdbinit", homedir);
- if (access (initfile, R_OK) == 0)
- if (!setjmp (to_top_level))
- source_command (initfile);
- }
- /* Determine if current directory is the same as the home
- directory, so we don't source the same file twice. */
-
- bzero (&homebuf, sizeof (struct stat));
- bzero (&cwdbuf, sizeof (struct stat));
-
- stat(homedir, &homebuf);
- stat(".", &cwdbuf);
-
- samedir = bcmp(&homebuf, &cwdbuf, sizeof(struct stat)) == 0;
- }
- /* Read the input file in the current directory, *if* it isn't
- the same file (it should exist, also). */
- if (!samedir) {
- if (access (".gdbinit", R_OK) == 0)
- if (!setjmp (to_top_level))
- source_command (".gdbinit");
- if (access (".xgdbinit", R_OK) == 0)
- if (!setjmp (to_top_level))
- source_command (".xgdbinit");
- }
-}
-
-
-int
-main (argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
-{
- int count;
- int inhibit_gdbinit = 0;
- int quiet = 1;
- int batch = 0;
- register int i;
- char *cp;
-
- /* XXX Windows only for xgdb. */
- char *strrchr();
- if (cp = strrchr(argv[0], '/'))
- ++cp;
- else
- cp = argv[0];
- if (*cp != 'x')
- inhibit_windows = 1;
-
-#if defined (ALIGN_STACK_ON_STARTUP)
- i = (int) &count & 0x3;
- if (i != 0)
- alloca (4 - i);
-#endif
-
- quit_flag = 0;
- linesize = 100;
- line = (char *) xmalloc (linesize);
- *line = 0;
- 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 */
-
- /* Look for flag arguments. */
-
- for (i = 1; i < argc; i++)
- {
- if (!strcmp (argv[i], "-q") || !strcmp (argv[i], "-quiet"))
- quiet = 1;
- else if (!strcmp (argv[i], "-nx"))
- inhibit_gdbinit = 1;
- else if (!strcmp (argv[i], "-nw"))
- inhibit_windows = 1;
- else if (!strcmp (argv[i], "-batch"))
- batch = 1, quiet = 1;
- else if (!strcmp (argv[i], "-fullname"))
- frame_file_full_name = 1;
- else if (!strcmp (argv[i], "-xgdb_verbose"))
- xgdb_verbose = 1;
- /* -help: print a summary of command line switches. */
- else if (!strcmp (argv[i], "-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\
- -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\
- -k Kernel debugging.\n\
- -w Writeable text.\n\
- -v Print GNU message and version number on startup.\n\
- -nc Don't confirm quit or run commands.\n\
-\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);
- }
-#ifdef KERNELDEBUG
- else if (!strcmp (argv[i], "-k"))
- kernel_debugging = 1;
-#endif
- else if (!strcmp (argv[i], "-w"))
- writeable_text = 1;
- else if (!strcmp (argv[i], "-v"))
- quiet = 0;
- else if (!strcmp (argv[i], "-nc"))
- inhibit_confirm = 1;
- else if (argv[i][0] == '-')
- /* Other options take arguments, so don't confuse an
- argument with an option. */
- i++;
- }
-
- /* 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 */
- initialize_signals ();
-
- if (!quiet)
- print_gdb_version ();
-
- /* Process the command line arguments. */
-
- count = 0;
- for (i = 1; i < argc; i++)
- {
- extern void exec_file_command (), symbol_file_command ();
- extern void core_file_command ();
- register char *arg = argv[i];
- /* Args starting with - say what to do with the following arg
- as a filename. */
- if (arg[0] == '-')
- {
- extern void tty_command (), directory_command ();
-
- if (!strcmp (arg, "-q") || !strcmp (arg, "-nx")
- || !strcmp (arg, "-quiet") || !strcmp (arg, "-batch")
- || !strcmp (arg, "-fullname") || !strcmp (arg, "-nw")
- || !strcmp (arg, "-xgdb_verbose")
- || !strcmp (arg, "-help")
- || !strcmp (arg, "-k")
- || !strcmp (arg, "-w")
- || !strcmp (arg, "-v")
- || !strcmp (arg, "-nc"))
- /* Already processed above */
- continue;
-
- if (++i == argc)
- fprintf (stderr, "No argument follows \"%s\".\n", arg);
- if (!setjmp (to_top_level))
- {
- /* -s foo: get syms from foo. -e foo: execute foo.
- -se foo: do both with foo. -c foo: use foo as core dump. */
- if (!strcmp (arg, "-se"))
- {
- exec_file_command (argv[i], !batch);
- symbol_file_command (argv[i], !batch);
- }
- else if (!strcmp (arg, "-s") || !strcmp (arg, "-symbols"))
- symbol_file_command (argv[i], !batch);
- else if (!strcmp (arg, "-e") || !strcmp (arg, "-exec"))
- exec_file_command (argv[i], !batch);
- else if (!strcmp (arg, "-c") || !strcmp (arg, "-core"))
- core_file_command (argv[i], !batch);
- /* -x foo: execute commands from foo. */
- else if (!strcmp (arg, "-x") || !strcmp (arg, "-command")
- || !strcmp (arg, "-commands"))
- source_command (argv[i]);
- /* -d foo: add directory `foo' to source-file directory
- search-list */
- else if (!strcmp (arg, "-d") || !strcmp (arg, "-dir")
- || !strcmp (arg, "-directory"))
- directory_command (argv[i], 0);
- /* -cd FOO: specify current directory as FOO.
- GDB remembers the precise string FOO as the dirname. */
- else if (!strcmp (arg, "-cd"))
- {
- cd_command (argv[i], 0);
- init_source_path ();
- }
- /* -t /def/ttyp1: use /dev/ttyp1 for inferior I/O. */
- else if (!strcmp (arg, "-t") || !strcmp (arg, "-tty"))
- tty_command (argv[i], 0);
-
- else
- error ("Unknown command-line switch: \"%s\"\n", arg);
- }
- }
- else
- {
- /* Args not thus accounted for
- are treated as, first, the symbol/executable file
- and, second, the core dump file. */
- count++;
- if (!setjmp (to_top_level))
- switch (count)
- {
- case 1:
- exec_file_command (arg, !batch);
- symbol_file_command (arg, !batch);
- break;
-
- case 2:
- core_file_command (arg, !batch);
- break;
-
- case 3:
- fprintf (stderr, "Excess command line args ignored. (%s%s)\n",
- arg, (i == argc - 1) ? "" : " ...");
- }
- }
- }
-
- if (!inhibit_gdbinit)
- source_init_files();
-
- if (batch)
- {
-#if 0
- fatal ("Attempt to read commands from stdin in batch mode.");
-#endif
- /* We have hit the end of the batch file. */
- exit (0);
- }
-
- if (!quiet)
- printf ("Type \"help\" for a list of commands.\n");
-
- /* The command loop. */
-
- while (1)
- {
- if (!setjmp (to_top_level))
- command_loop ();
- if (ISATTY(stdin))
- clearerr (stdin); /* Don't get hung if C-d is typed. */
- else if (feof(instream)) /* Avoid endless loops for redirected stdin */
- break;
- }
- exit (0);
-}
-
-
-static void
-do_nothing ()
-{
-}
-
-/* Read commands from `instream' and execute them
- until end of file. */
-void
-command_loop ()
-{
- struct cleanup *old_chain;
- register int toplevel = (instream == stdin);
- register int interactive = (toplevel && ISATTY(stdin));
-
- while (!feof (instream))
- {
- register char *cmd_line;
-
- quit_flag = 0;
- if (interactive)
- reinitialize_more_filter ();
- old_chain = make_cleanup (do_nothing, 0);
- cmd_line = command_line_input (prompt, toplevel);
- execute_command (cmd_line, toplevel);
- /* Do any commands attached to breakpoint we stopped at. */
- do_breakpoint_commands ();
- do_cleanups (old_chain);
- }
-}
-
-/* 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;
-}
-
-/* Read a line from the stream "instream" without command line editing.
-
- It prints PROMPT once at the start.
- Action is compatible with "readline" (i.e., space for typing is
- malloced & should be freed by caller). */
-char *
-gdb_readline (prompt)
- char *prompt;
-{
- int c;
- char *result;
- int input_index = 0;
- int result_size = 80;
-
- if (prompt)
- {
- printf (prompt);
- fflush (stdout);
- }
-
- result = (char *) xmalloc (result_size);
-
- while (1)
- {
- c = fgetc (instream ? instream : stdin);
- if (c == EOF)
- {
- free(result);
- return ((char *)0);
- }
- if (c == '\n')
- break;
-
- result[input_index++] = c;
- if (input_index >= result_size)
- {
- result_size <= 1;
- result = (char *)xrealloc(result, result_size);
- }
- }
- result[input_index++] = '\0';
- return result;
-}
-
-/* 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. */
-
-/* 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. */
-char *
-symbol_completion_function (text, state)
- char *text;
- int state;
-{
- char **make_symbol_completion_list ();
- 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 (p + strlen(text) != tmp_command + rl_point)
- 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 = make_symbol_completion_list ("");
- }
- else
- {
- if (c->prefixlist && !c->allow_unknown)
- {
- *p = '\0';
- error ("\"%s\" command requires a subcommand.",
- tmp_command);
- }
- else
- list = make_symbol_completion_list (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);
-}
-
-
-void
-print_prompt ()
-{
- if (prompt)
- {
- printf ("%s", prompt);
- fflush (stdout);
- }
-}
-
-
-#ifdef HAVE_TERMIO
-#include <termio.h>
-static struct termio norm_tty;
-
-static void
-suspend_sig()
-{
- int tty = fileno(stdin);
- struct termio cur_tty;
-
- ioctl(tty, TCGETA, &cur_tty);
- ioctl(tty, TCSETAW, &norm_tty);
-
- (void) sigsetmask(0);
- signal(SIGTSTP, SIG_DFL);
- kill(0, SIGTSTP);
-
- /*
- * we've just been resumed -- current tty params become new
- * 'normal' params (in case tset/stty was done while we were
- * suspended). Merge values that readline might have changed
- * into new params, then restore term mode.
- */
- ioctl(tty, TCGETA, &norm_tty);
- cur_tty.c_lflag = (cur_tty.c_lflag & (ICANON|ECHO|ISIG)) |
- (norm_tty.c_lflag &~ (ICANON|ECHO|ISIG));
- cur_tty.c_iflag = (cur_tty.c_iflag & (IXON|ISTRIP|INPCK)) |
- (norm_tty.c_iflag &~ (IXON|ISTRIP|INPCK));
- ioctl(tty, TCSETAW, &cur_tty);
-
- signal(SIGTSTP, suspend_sig);
- print_prompt();
-
- /*
- * Forget about any previous command -- null line now will do
- * nothing.
- */
- dont_repeat();
-}
-
-#else
-
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <sgtty.h>
-
-static struct sgttyb norm_tty;
-static struct tchars norm_tchars;
-static struct ltchars norm_ltchars;
-static int norm_lflags;
-
-#ifdef PASS8
-#define RL_TFLAGS (RAW|CRMOD|ECHO|CBREAK|PASS8)
-#else
-#define RL_TFLAGS (RAW|CRMOD|ECHO|CBREAK)
-#endif
-
-static void
-suspend_sig()
-{
- int tty = fileno(stdin);
- struct sgttyb cur_tty;
- struct tchars cur_tchars;
- struct ltchars cur_ltchars;
- int cur_lflags;
- int cur_flags;
-
- ioctl(tty, TIOCGETP, &cur_tty);
- ioctl(tty, TIOCGETC, &cur_tchars);
- ioctl(tty, TIOCLGET, &cur_lflags);
- ioctl(tty, TIOCGLTC, &cur_ltchars);
-
- ioctl(tty, TIOCSETP, &norm_tty);
- ioctl(tty, TIOCSETC, &norm_tchars);
- ioctl(tty, TIOCLSET, &norm_lflags);
- ioctl(tty, TIOCSLTC, &norm_ltchars);
-
- (void) sigsetmask(0);
- signal(SIGTSTP, SIG_DFL);
- kill(0, SIGTSTP);
-
- /*
- * we've just been resumed -- current tty params become new
- * 'normal' params (in case tset/stty was done while we were
- * suspended). Merge values that readline might have changed
- * into new params, then restore term mode.
- */
- ioctl(tty, TIOCGETP, &norm_tty);
- cur_flags = cur_tty.sg_flags;
- cur_tty = norm_tty;
- cur_tty.sg_flags = (cur_tty.sg_flags &~ RL_TFLAGS)
- | (cur_flags & RL_TFLAGS);
-
- ioctl(tty, TIOCLGET, &norm_lflags);
-#ifdef LPASS8
- cur_lflags = (cur_lflags &~ LPASS8) | (cur_flags & LPASS8);
-#endif
- ioctl(tty, TIOCGETC, &norm_tchars);
- ioctl(tty, TIOCGLTC, &norm_ltchars);
-
- ioctl(tty, TIOCSETP, &cur_tty);
- ioctl(tty, TIOCSETC, &cur_tchars);
- ioctl(tty, TIOCLSET, &cur_lflags);
- ioctl(tty, TIOCSLTC, &cur_ltchars);
-
- signal(SIGTSTP, suspend_sig);
- print_prompt();
-
- /*
- * Forget about any previous command -- null line now will do
- * nothing.
- */
- dont_repeat();
-}
-#endif /* HAVE_TERMIO */
-
-/* Initialize signal handlers. */
-initialize_signals ()
-{
- extern void request_quit ();
- int tty = fileno(stdin);
-
- 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);
-
- ioctl(tty, TIOCGETP, &norm_tty);
- ioctl(tty, TIOCLGET, &norm_lflags);
- ioctl(tty, TIOCGETC, &norm_tchars);
- ioctl(tty, TIOCGLTC, &norm_ltchars);
- signal(SIGTSTP, suspend_sig);
-}
-
-char *
-finish_command_input(inputline, repeat, interactive)
- register char *inputline;
- int repeat;
- int interactive;
-{
- static char *do_free;
-
- if (do_free) {
- free(do_free);
- do_free = NULL;
- }
-
- /* Do history expansion if that is wished. */
- if (interactive && history_expansion_p) {
- int expanded;
-
- expanded = history_expand(inputline, &do_free);
- if (expanded) {
- /* Print the changes. */
- puts(do_free);
-
- /* An error acts like no input. */
- if (expanded < 0) {
- *do_free = 0;
- return (do_free);
- }
- }
- inputline = do_free;
- }
- /* get rid of any leading whitespace */
- while (isspace(*inputline))
- ++inputline;
- /*
- * If we just got an empty line, and that is supposed to repeat the
- * previous command, return the value in the global buffer.
- */
- if (*inputline == 0) {
- if (repeat)
- return (line);
- } else if (interactive)
- add_history(inputline);
-
- /*
- * If line is a comment, clear it out.
- * Note: 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 '#'.
- */
- if (*inputline == '#')
- *inputline = 0;
- else if (repeat) {
- /* Save into global buffer. */
- register int i = strlen(inputline) + 1;
-
- if (i > linesize) {
- line = xrealloc(line, i);
- linesize = i;
- }
- strcpy(line, inputline);
- }
- return (inputline);
-}
-
-static char *
-get_a_cmd_line(prompt, interactive)
- char *prompt;
- int interactive;
-{
- register char *cp;
-
- /* Control-C quits instantly if typed while reading input. */
- immediate_quit++;
- if (interactive && command_editing_p) {
- extern void (*rl_event_hook)();
-
- rl_event_hook = window_hook;
- cp = readline(prompt);
- } else {
- if (interactive) {
- if (window_hook) {
- print_prompt();
- (*window_hook)();
- }
- } else
- prompt = NULL;
- cp = gdb_readline(prompt);
- }
- --immediate_quit;
- return (cp);
-}
-
-/* Read one line from the command input stream `instream'
- Returns the address of the start of the line.
-
- *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(prompt, repeat)
- char *prompt;
- int repeat;
-{
- static char *do_free;
- register int interactive = (instream == stdin && ISATTY(instream));
- register char *cp;
- register int i;
-
- if (do_free) {
- free(do_free);
- do_free = NULL;
- }
- cp = get_a_cmd_line(prompt, interactive);
-
- /*
- * handle continued lines (this loop is not particularly
- * efficient because it's rare).
- */
- while (cp && cp[i = strlen(cp) - 1] == '\\') {
- register char *np = get_a_cmd_line(prompt, interactive);
- register int j;
-
- if (np == NULL) {
- cp[i] = 0;
- break;
- }
- j = strlen(np);
- cp = xrealloc(cp, i + j + 1);
- strcpy(cp + i, np);
- free(np);
- }
- if (cp == NULL)
- return ("");
- do_free = cp;
- return (finish_command_input(cp, repeat, interactive));
-}
-
-
-#define MAX_USER_ARGS 32
-
-static struct user_args {
- struct {
- char *arg;
- int len;
- } a[10];
-} uargs[MAX_USER_ARGS];
-
-static struct user_args *user_arg = uargs;
-
-static void
-arg_cleanup(ap)
- struct user_args *ap;
-{
- user_arg = ap;
-}
-
-/* Bind arguments $arg0, $arg1, ..., for a user defined command. */
-struct cleanup *
-setup_user_args(p)
- char *p;
-{
- register int i;
- struct cleanup *old_chain = make_cleanup(arg_cleanup, user_arg);
-
- if (++user_arg >= &uargs[MAX_USER_ARGS])
- error("user defined functions nested too deeply\n");
-
- bzero(user_arg, sizeof(*user_arg));
-
- i = 0;
- while (*p) {
- while (isspace(*p))
- ++p;
- user_arg->a[i].arg = p;
- while (*p && ! isspace(*p))
- ++p;
- user_arg->a[i].len = p - user_arg->a[i].arg;
- ++i;
- }
- return (old_chain);
-}
-
-static char *
-findarg(str)
- register char *str;
-{
- register char *cp = str;
- extern char *index();
-
- while (cp = index(cp, '$')) {
- if (strncmp(cp, "$arg", 4) == 0 && isdigit(cp[4]))
- return (cp);
- ++cp;
- }
- return (char *)0;
-}
-
-/* expand arguments from "line" into "new" */
-static void
-expand_args(line, new)
- register char *line, *new;
-{
- register char *cp = findarg(line);
-
- while (cp = findarg(line)) {
- int i, len;
-
- bcopy(line, new, cp - line);
- new += cp - line;
- i = cp[4] - '0';
- if (len = user_arg->a[i].len) {
- bcopy(user_arg->a[i].arg, new, len);
- new += len;
- }
- line = cp + 5;
- }
- strcpy(new, line);
-}
-
-/* expand any arguments in "line" then execute the result */
-static void
-expand_and_execute(line, from_tty)
- char *line;
- int from_tty;
-{
- void execute_command();
- char new[1024];
-
- if (! findarg(line)) {
- execute_command(line, from_tty);
- return;
- }
- expand_args(line, new);
- execute_command(new, from_tty);
-}
-
-char *
-read_one_command_line(prompt, from_tty)
- char *prompt;
-{
- register char *p, *p1;
-
- dont_repeat();
- p = command_line_input(prompt, from_tty);
-
- /* Remove trailing blanks. */
- p1 = p + strlen(p);
- while (--p1 > p && (*p1 == ' ' || *p1 == '\t'))
- ;
- *++p1 = 0;
- return (p);
-}
-
-static char cmd_prompt[] = " > ";
-
-int
-parse_control_structure(rootcmd, from_tty, level)
- struct command_line *rootcmd;
- int from_tty;
-{
- struct command_line *cmd = (struct command_line *)xmalloc(sizeof(*cmd));
- char *prompt;
-
- ++level;
- prompt = from_tty? &cmd_prompt[sizeof(cmd_prompt) - 1 - 2*level] :
- (char *)0;
- bzero(cmd, sizeof(*cmd));
- rootcmd->body = cmd;
- while (1) {
- char *p = read_one_command_line(prompt, from_tty);
-
- p = savestring(p, strlen(p));
- cmd->line = p;
- if (!strncmp(p, "while ", 6)) {
- cmd->type = CL_WHILE;
- if (parse_control_structure(cmd, from_tty, level))
- return (1);
- } else if (!strncmp(p, "if ", 3)) {
- cmd->type = CL_IF;
- if (parse_control_structure(cmd, from_tty, level)) {
- struct command_line *tmp;
- int stat;
-
- cmd->elsebody = cmd->body;
- stat = parse_control_structure(cmd, from_tty,
- level);
- tmp = cmd->elsebody;
- cmd->elsebody = cmd->body;
- cmd->body = tmp;
- if (stat)
- return (1);
- }
- } else if (!strcmp(p, "else")) {
- cmd->type = CL_END;
- return (1);
- } else if (!strcmp(p, "end")) {
- cmd->type = CL_END;
- return (0);
- } else if (!strcmp(p, "exitloop")) {
- cmd->type = CL_EXITLOOP;
- } else {
- cmd->type = CL_NORMAL;
- }
- cmd->next = (struct command_line *)xmalloc(sizeof(*cmd));
- cmd = cmd->next;
- bzero(cmd, sizeof(*cmd));
- }
- /* NOTREACHED */
-}
-
-int
-execute_control_structure(cmd)
- register struct command_line *cmd;
-{
- char expn[1024];
- struct expression *cond;
- int stat;
-
- while (cmd) {
- QUIT;
- switch (cmd->type) {
- case CL_END:
- return (0);
- case CL_NORMAL:
- expand_and_execute(cmd->line, 0);
- break;
- case CL_WHILE:
- expand_args(cmd->line + 6, expn);
- cond = parse_c_expression(expn);
- while (breakpoint_cond_eval(cond) == 0)
- if (execute_control_structure(cmd->body))
- break;
- free(cond);
- break;
- case CL_IF:
- expand_args(cmd->line + 3, expn);
- cond = parse_c_expression(expn);
- stat = breakpoint_cond_eval(cond);
- free(cond);
- if (stat == 0) {
- if (execute_control_structure(cmd->body))
- return (1);
- } else if (cmd->elsebody) {
- if (execute_control_structure(cmd->elsebody))
- return (1);
- }
- break;
- case CL_EXITLOOP:
- return (1);
- }
- cmd = cmd->next;
- }
- free_all_values();
-}
-
-execute_command_lines(cmd)
- struct command_line *cmd;
-{
- struct cleanup *old_chain = make_cleanup(source_cleanup, instream);
-
- /*
- * Set the instream to 0, indicating execution of a user-defined
- * function.
- */
- ++immediate_quit;
- instream = (FILE *) 0;
- (void)execute_control_structure(cmd);
- --immediate_quit;
- do_cleanups(old_chain);
-}
-
-/* do following command lines if expression true */
-if_command(p, from_tty)
- char *p;
- int from_tty;
-{
- struct cleanup *old_chain;
- struct command_line *cmd = (struct command_line *)xmalloc(sizeof(*cmd));
- char buf[128];
-
- sprintf(buf, "if %s", p);
-
- bzero(cmd, sizeof(*cmd));
- old_chain = make_cleanup(free_command_lines, cmd);
- cmd->type = CL_IF;
- cmd->line = savestring(buf, strlen(buf));
- /* XXX cmd->line? */
- if (parse_control_structure(cmd, from_tty, 0)) {
- struct command_line *tmp;
-
- cmd->elsebody = cmd->body;
- (void) parse_control_structure(cmd, from_tty, 0);
- tmp = cmd->elsebody;
- cmd->elsebody = cmd->body;
- cmd->body = tmp;
- }
- (void) execute_command_lines(cmd);
- do_cleanups(old_chain);
-}
-
-/* do following command lines while expression true */
-while_command(p, from_tty)
- char *p;
- int from_tty;
-{
- struct cleanup *old_chain;
- struct command_line *cmd = (struct command_line *)xmalloc(sizeof(*cmd));
- char buf[128];
-
- sprintf(buf, "while %s", p);
-
- bzero(cmd, sizeof(*cmd));
- old_chain = make_cleanup(free_command_lines, cmd);
- cmd->type = CL_WHILE;
- cmd->line = savestring(buf, strlen(buf));
- (void)parse_control_structure(cmd, from_tty, 0);
- (void)execute_command_lines(cmd);
- do_cleanups(old_chain);
-}
-
-/*
- * 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();
- if (*p) {
- c = lookup_cmd(&p, cmdlist, "", 0, 1);
- if (c->function == 0)
- error("That is not a command, just a help topic.");
- else if (c->class == (int) class_user) {
- struct cleanup *old_chain = setup_user_args(p);
-
- cmdlines = (struct command_line *) c->function;
- if (cmdlines)
- (void)execute_command_lines(cmdlines);
-
- do_cleanups(old_chain);
- } else
- /* Pass null arg rather than an empty one. */
- (*c->function) (*p ? p : 0, from_tty);
- }
-}
-
-/*
- * 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(from_tty)
- int from_tty;
-{
- struct cleanup *old_chain;
- struct command_line *cmd = (struct command_line *)xmalloc(sizeof(*cmd));
- struct command_line *next;
-
- bzero(cmd, sizeof(*cmd));
- old_chain = make_cleanup(free_command_lines, cmd);
- cmd->type = CL_NOP;
- (void)parse_control_structure(cmd, from_tty, 0);
- dont_repeat();
- discard_cleanups(old_chain);
- next = cmd->body;
- free(cmd);
- return (next);
-}
-
-/* Free a chain of struct command_line's. */
-
-void
-free_command_lines(cmds)
- struct command_line *cmds;
-{
- struct command_line *next;
-
- while (cmds) {
- if (cmds->body)
- free(cmds->body);
- if (cmds->elsebody)
- free(cmds->elsebody);
- if (cmds->line)
- free(cmds->line);
- next = cmds->next;
- free(cmds);
- cmds = next;
- }
-}
-
-/* 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. */
-
-static void
-info_command ()
-{
- printf ("\"info\" must be followed by the name of an info command.\n");
- help_list (infolist, "info ", -1, stdout);
-}
-
-/* Add an element to the list of commands. */
-
-void
-add_com (name, class, fun, doc)
- char *name;
- int 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;
- int 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);
-}
-
-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;
- char *tem = comname;
-
- validate_comname (comname);
-
- c = lookup_cmd (&tem, cmdlist, "", -1, 1);
- if (c)
- {
- if (c->class == (int) class_user || c->class == (int) 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 (from_tty);
-
- if (c && c->class == (int) class_user)
- free_command_lines (c->function);
-
- add_com (comname, class_user, cmds,
- (c && c->class == (int) class_user)
- ? c->doc : savestring ("User-defined.", 13));
-}
-
-static void
-document_command (comname, from_tty)
- char *comname;
- int from_tty;
-{
- register struct cmd_list_element *c;
- register char *p;
- register char *cp;
- register char *doc = 0;
- register int len;
- char *tmp = comname;
-
- validate_comname (comname);
- c = lookup_cmd (&tmp, cmdlist, "", 0, 1);
- if (c->class != (int) class_user)
- error ("Command \"%s\" is built-in.", comname);
-
- if (from_tty)
- printf ("Type documentation for \"%s\". \
-End with a line saying just \"end\".\n", comname);
-
- while (p = read_one_command_line(from_tty? "> " : 0, from_tty))
- {
- if (strcmp(p, "end") == 0)
- break;
- len = strlen(p) + 1;
- if (! doc)
- {
- doc = xmalloc(len);
- cp = doc;
- }
- else
- {
- int i = cp - doc;
- doc = xrealloc(doc, i + len);
- cp = doc + i;
- }
- strcpy(cp, p);
- cp += len;
- cp[-1] = '\n';
- }
- if (doc && cp > doc)
- cp[-1] = 0;
- if (c->doc)
- free (c->doc);
- c->doc = doc;
-}
-
-static void
-print_gdb_version ()
-{
- printf ("GDB %s, Copyright (C) 1989 Free Software Foundation, Inc.\n\
-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",
- version);
-}
-
-static void
-version_info ()
-{
- immediate_quit++;
- print_gdb_version ();
- immediate_quit--;
-}
-
-
-/* Command to specify a prompt string instead of "(gdb) ". */
-
-void
-set_prompt_command (text)
- char *text;
-{
- char *p, *q;
- register int c;
- char *new;
-
- if (text == 0)
- error_no_arg ("string to which to set prompt");
-
- new = (char *) xmalloc (strlen (text) + 2);
- p = text; q = new;
- while (c = *p++)
- {
- if (c == '\\')
- {
- /* \ at end of argument is used after spaces
- so they won't be lost. */
- if (*p == 0)
- break;
- c = parse_escape (&p);
- if (c == 0)
- break; /* C loses */
- else if (c > 0)
- *q++ = c;
- }
- else
- *q++ = c;
- }
- if (*(p - 1) != '\\')
- *q++ = ' ';
- *q++ = '\0';
- new = (char *) xrealloc (new, q - new);
- free (prompt);
- prompt = new;
-}
-
-static void
-quit_command ()
-{
- extern void exec_file_command ();
- if (have_inferior_p ())
- {
- if (inhibit_confirm || query ("The program is running. Quit anyway? "))
- {
- /* Prevent any warning message from reopen_exec_file, in case
- we have a core file that's inconsistent with the exec file. */
- exec_file_command (0, 0);
- kill_inferior ();
- }
- 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;
-}
-
-static void
-pwd_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- if (arg) error ("The \"pwd\" command does not take an argument: %s", arg);
- 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);
-
- if (from_tty)
- pwd_command ((char *) 0, 1);
-}
-
-static void
-source_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- FILE *stream;
- struct cleanup *cleanups;
- char *file = arg;
- char *path;
-
- if (file == 0)
- /* Let source without arguments read .gdbinit. */
- file = ".gdbinit";
-
- file = tilde_expand (file);
- make_cleanup (free, file);
-
-#ifdef KERNELDEBUG
- if (path = getenv(kernel_debugging? "KGDBPATH" : "GDBPATH"))
-#else
- if (path = getenv("GDBPATH"))
-#endif
- {
- int fd = openp(path, 1, file, O_RDONLY, 0, 0);
-
- if (fd == -1)
- stream = 0;
- else
- stream = fdopen(fd, "r");
- }
- else
- stream = fopen (file, "r");
-
- if (stream == 0)
- perror_with_name (file);
-
- cleanups = make_cleanup (source_cleanup, instream);
-
- instream = stream;
-
- command_loop ();
-
- do_cleanups (cleanups);
-}
-
-static void
-echo_command (text)
- char *text;
-{
- 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);
- }
- fflush(stdout);
-}
-
-static void
-dump_me_command ()
-{
- if (query ("Should GDB dump core? "))
- {
- signal (SIGQUIT, SIG_DFL);
- kill (getpid (), SIGQUIT);
- }
-}
-
-int
-parse_binary_operation (caller, arg)
- char *caller, *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 ("\"%s\" not given a binary valued argument.", caller);
-}
-
-/* Functions to manipulate command line editing control variables. */
-
-static void
-set_editing (arg, from_tty)
- char *arg;
- int from_tty;
-{
- command_editing_p = parse_binary_operation ("set command-editing", arg);
-}
-
-/* Number of commands to print in each call to editing_info. */
-#define Hist_print 10
-static void
-editing_info (arg, from_tty)
- char *arg;
- 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 {
- char *line;
- char *data;
- } *history_get();
- extern int history_base;
-
- 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 : "");
-
- /* 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 (arg)
- {
- if (arg[0] == '+' && arg[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 (arg) - 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 (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");
-
- 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 && arg)
- {
- arg[0] = '+';
- arg[1] = '\0';
- }
-}
-
-static void
-set_history_expansion (arg, from_tty)
- char *arg;
- int from_tty;
-{
- history_expansion_p = parse_binary_operation ("set history expansion", arg);
-}
-
-static void
-set_history_write (arg, from_tty)
- char *arg;
- int from_tty;
-{
- write_history_p = parse_binary_operation ("set history write", arg);
-}
-
-static void
-set_history (arg, from_tty)
- char *arg;
- 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
-set_history_size (arg, from_tty)
- char *arg;
- int from_tty;
-{
- if (!*arg)
- error_no_arg ("set history size");
-
- history_size = atoi (arg);
-}
-
-static void
-set_history_filename (arg, from_tty)
- char *arg;
- int from_tty;
-{
- int i;
-
- if (!arg)
- error_no_arg ("history file name");
-
- arg = tilde_expand (arg);
- make_cleanup (free, arg);
-
- i = strlen (arg) - 1;
-
- free (history_filename);
-
- while (i > 0 && (arg[i] == ' ' || arg[i] == '\t'))
- i--;
- ++i;
-
- if (!*arg)
- history_filename = (char *) 0;
- else
- history_filename = savestring (arg, i + 1);
- history_filename[i] = '\0';
-}
-
-int info_verbose;
-
-static void
-set_verbose_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- info_verbose = parse_binary_operation ("set verbose", arg);
-}
-
-static void
-verbose_info (arg, from_tty)
- char *arg;
- int from_tty;
-{
- if (arg)
- error ("\"info verbose\" does not take any arguments.\n");
-
- printf ("Verbose printing of information is %s.\n",
- info_verbose ? "on" : "off");
-}
-
-static void
-float_handler ()
-{
- error ("Invalid floating value encountered or computed.");
-}
-
-
-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;
- sethistlist = (struct cmd_list_element *) 0;
- unsethistlist = (struct cmd_list_element *) 0;
-}
-
-static void
-initialize_main ()
-{
- char *tmpenv;
- /* Command line editing externals. */
- extern int (*rl_completion_entry_function)();
- extern char *rl_completer_word_break_characters;
- extern char *rl_readline_name;
-
- /* Set default verbose mode on. */
- info_verbose = 1;
-
-#ifdef KERNELDEBUG
- if (kernel_debugging)
- prompt = savestring ("(kgdb) ", 7);
- else
-#endif
- prompt = savestring ("(gdb) ", 6);
-
- /* 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, 0, "Obscure features.", &cmdlist);
- add_cmd ("alias", class_alias, 0, "Aliases of other commands.", &cmdlist);
- add_cmd ("user", class_user, 0, "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, 0, "Support facilities.", &cmdlist);
- add_cmd ("status", class_info, 0, "Status inquiries.", &cmdlist);
- add_cmd ("files", class_files, 0, "Specifying and examining files.", &cmdlist);
- add_cmd ("breakpoints", class_breakpoint, 0, "Making program stop at certain points.", &cmdlist);
- add_cmd ("data", class_vars, 0, "Examining data.", &cmdlist);
- add_cmd ("stack", class_stack, 0, "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, 0, "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_cmd ("prompt", class_support, set_prompt_command,
- "Change gdb's prompt from the default of \"(gdb)\"",
- &setlist);
- 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.");
-
- 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.");
- 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);
- add_com ("while", class_support, while_command,
- "execute following commands while condition is true.\n\
-Expression for condition follows \"while\" keyword.");
- add_com ("if", class_support, if_command,
- "execute following commands if condition is true.\n\
-Expression for condition follows \"if\" keyword.");
- add_cmd ("verbose", class_support, set_verbose_command,
- "Change the number of informational messages gdb prints.",
- &setlist);
- add_info ("verbose", verbose_info,
- "Status of gdb's verbose printing option.\n");
-
- add_com ("dump-me", class_obscure, dump_me_command,
- "Get fatal error; make debugger dump its core.");
-
- add_cmd ("editing", class_support, set_editing,
- "Enable or disable 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);
-
- add_prefix_cmd ("history", class_support, set_history,
- "Generic command for setting command history parameters.",
- &sethistlist, "set history ", 0, &setlist);
-
- add_cmd ("expansion", no_class, set_history_expansion,
- "Enable or disable history expansion on command input.\n\
-Without an argument, history expansion is enabled.", &sethistlist);
-
- add_cmd ("write", no_class, set_history_write,
- "Enable or disable 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);
-
- add_cmd ("size", no_class, set_history_size,
- "Set the size of the command history, \n\
-ie. the number of previous commands to keep a record of.", &sethistlist);
-
- add_cmd ("filename", no_class, set_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);
-
- 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_info ("editing", editing_info, "Status of command editor.");
-
- add_info ("version", version_info, "Report what version of GDB this is.");
-}
diff --git a/gnu/usr.bin/gdb/mmalloc/Makefile b/gnu/usr.bin/gdb/mmalloc/Makefile
new file mode 100644
index 000000000000..1ef0d1dd0e37
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/Makefile
@@ -0,0 +1,10 @@
+LIB= mmalloc
+SRCS= mcalloc.c mfree.c mmalloc.c mmcheck.c mmemalign.c mmstats.c \
+ mmtrace.c mrealloc.c mvalloc.c mmap-sup.c attach.c detach.c keys.c \
+ sbrk-sup.c
+
+NOPROFILE=no
+NOPIC=no
+install:
+ @echo -n
+.include <bsd.lib.mk>
diff --git a/gnu/usr.bin/gdb/mmalloc/README.FreeBSD b/gnu/usr.bin/gdb/mmalloc/README.FreeBSD
new file mode 100644
index 000000000000..338400ffa885
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/README.FreeBSD
@@ -0,0 +1,7 @@
+This is a greatly pared down libmmalloc directory. Only what's required to build
+gdb-4.12 on FreeBSD was kept.
+
+This is temporary. In FreeBSD 2.0 a fully ported libmmalloc will likely appear
+as a system library for use by all the build tools.
+
+paul@freefall.cdrom.com
diff --git a/gnu/usr.bin/gdb/mmalloc/attach.c b/gnu/usr.bin/gdb/mmalloc/attach.c
new file mode 100644
index 000000000000..6737fca38723
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/attach.c
@@ -0,0 +1,218 @@
+/* Initialization for access to a mmap'd malloc managed region.
+ Copyright 1992 Free Software Foundation, Inc.
+
+ Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com
+
+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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <fcntl.h> /* After sys/types.h, at least for dpx/2. */
+#include <sys/stat.h>
+#include <string.h>
+#include "mmalloc.h"
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+
+#if defined(HAVE_MMAP)
+
+/* Forward declarations/prototypes for local functions */
+
+static struct mdesc *reuse PARAMS ((int));
+
+/* Initialize access to a mmalloc managed region.
+
+ If FD is a valid file descriptor for an open file then data for the
+ mmalloc managed region is mapped to that file, otherwise "/dev/zero"
+ is used and the data will not exist in any filesystem object.
+
+ If the open file corresponding to FD is from a previous use of
+ mmalloc and passes some basic sanity checks to ensure that it is
+ compatible with the current mmalloc package, then it's data is
+ mapped in and is immediately accessible at the same addresses in
+ the current process as the process that created the file.
+
+ If BASEADDR is not NULL, the mapping is established starting at the
+ specified address in the process address space. If BASEADDR is NULL,
+ the mmalloc package chooses a suitable address at which to start the
+ mapped region, which will be the value of the previous mapping if
+ opening an existing file which was previously built by mmalloc, or
+ for new files will be a value chosen by mmap.
+
+ Specifying BASEADDR provides more control over where the regions
+ start and how big they can be before bumping into existing mapped
+ regions or future mapped regions.
+
+ On success, returns a "malloc descriptor" which is used in subsequent
+ calls to other mmalloc package functions. It is explicitly "void *"
+ ("char *" for systems that don't fully support void) so that users
+ of the package don't have to worry about the actual implementation
+ details.
+
+ On failure returns NULL. */
+
+PTR
+mmalloc_attach (fd, baseaddr)
+ int fd;
+ PTR baseaddr;
+{
+ struct mdesc mtemp;
+ struct mdesc *mdp;
+ PTR mbase;
+ struct stat sbuf;
+
+ /* First check to see if FD is a valid file descriptor, and if so, see
+ if the file has any current contents (size > 0). If it does, then
+ attempt to reuse the file. If we can't reuse the file, either
+ because it isn't a valid mmalloc produced file, was produced by an
+ obsolete version, or any other reason, then we fail to attach to
+ this file. */
+
+ if (fd >= 0)
+ {
+ if (fstat (fd, &sbuf) < 0)
+ {
+ return (NULL);
+ }
+ else if (sbuf.st_size > 0)
+ {
+ return ((PTR) reuse (fd));
+ }
+ }
+
+ /* We start off with the malloc descriptor allocated on the stack, until
+ we build it up enough to call _mmalloc_mmap_morecore() to allocate the
+ first page of the region and copy it there. Ensure that it is zero'd and
+ then initialize the fields that we know values for. */
+
+ mdp = &mtemp;
+ memset ((char *) mdp, 0, sizeof (mtemp));
+ strncpy (mdp -> magic, MMALLOC_MAGIC, MMALLOC_MAGIC_SIZE);
+ mdp -> headersize = sizeof (mtemp);
+ mdp -> version = MMALLOC_VERSION;
+ mdp -> morecore = __mmalloc_mmap_morecore;
+ mdp -> fd = fd;
+ mdp -> base = mdp -> breakval = mdp -> top = baseaddr;
+
+ /* If we have not been passed a valid open file descriptor for the file
+ to map to, then open /dev/zero and use that to map to. */
+
+ if (mdp -> fd < 0)
+ {
+ if ((mdp -> fd = open ("/dev/zero", O_RDWR)) < 0)
+ {
+ return (NULL);
+ }
+ else
+ {
+ mdp -> flags |= MMALLOC_DEVZERO;
+ }
+ }
+
+ /* Now try to map in the first page, copy the malloc descriptor structure
+ there, and arrange to return a pointer to this new copy. If the mapping
+ fails, then close the file descriptor if it was opened by us, and arrange
+ to return a NULL. */
+
+ if ((mbase = mdp -> morecore (mdp, sizeof (mtemp))) != NULL)
+ {
+ memcpy (mbase, mdp, sizeof (mtemp));
+ mdp = (struct mdesc *) mbase;
+ }
+ else
+ {
+ if (mdp -> flags & MMALLOC_DEVZERO)
+ {
+ close (mdp -> fd);
+ }
+ mdp = NULL;
+ }
+
+ return ((PTR) mdp);
+}
+
+/* Given an valid file descriptor on an open file, test to see if that file
+ is a valid mmalloc produced file, and if so, attempt to remap it into the
+ current process at the same address to which it was previously mapped.
+
+ Note that we have to update the file descriptor number in the malloc-
+ descriptor read from the file to match the current valid one, before
+ trying to map the file in, and again after a successful mapping and
+ after we've switched over to using the mapped in malloc descriptor
+ rather than the temporary one on the stack.
+
+ Once we've switched over to using the mapped in malloc descriptor, we
+ have to update the pointer to the morecore function, since it almost
+ certainly will be at a different address if the process reusing the
+ mapped region is from a different executable.
+
+ Also note that if the heap being remapped previously used the mmcheck()
+ routines, we need to update the hooks since their target functions
+ will have certainly moved if the executable has changed in any way.
+ We do this by calling mmcheck() internally.
+
+ Returns a pointer to the malloc descriptor if successful, or NULL if
+ unsuccessful for some reason. */
+
+static struct mdesc *
+reuse (fd)
+ int fd;
+{
+ struct mdesc mtemp;
+ struct mdesc *mdp = NULL;
+
+ if ((lseek (fd, 0L, SEEK_SET) == 0) &&
+ (read (fd, (char *) &mtemp, sizeof (mtemp)) == sizeof (mtemp)) &&
+ (mtemp.headersize == sizeof (mtemp)) &&
+ (strcmp (mtemp.magic, MMALLOC_MAGIC) == 0) &&
+ (mtemp.version <= MMALLOC_VERSION))
+ {
+ mtemp.fd = fd;
+ if (__mmalloc_remap_core (&mtemp) == mtemp.base)
+ {
+ mdp = (struct mdesc *) mtemp.base;
+ mdp -> fd = fd;
+ mdp -> morecore = __mmalloc_mmap_morecore;
+ if (mdp -> mfree_hook != NULL)
+ {
+ mmcheck ((PTR) mdp, (void (*) PARAMS ((void))) NULL);
+ }
+ }
+ }
+ return (mdp);
+}
+
+#else /* !defined (HAVE_MMAP) */
+
+/* For systems without mmap, the library still supplies an entry point
+ to link to, but trying to initialize access to an mmap'd managed region
+ always fails. */
+
+/* ARGSUSED */
+PTR
+mmalloc_attach (fd, baseaddr)
+ int fd;
+ PTR baseaddr;
+{
+ return (NULL);
+}
+
+#endif /* defined (HAVE_MMAP) */
+
diff --git a/gnu/usr.bin/gdb/mmalloc/detach.c b/gnu/usr.bin/gdb/mmalloc/detach.c
new file mode 100644
index 000000000000..03d632c20609
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/detach.c
@@ -0,0 +1,71 @@
+/* Finish access to a mmap'd malloc managed region.
+ Copyright 1992 Free Software Foundation, Inc.
+
+ Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com
+
+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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <fcntl.h> /* After sys/types.h, at least for dpx/2. */
+#include "mmalloc.h"
+
+/* Terminate access to a mmalloc managed region by unmapping all memory pages
+ associated with the region, and closing the file descriptor if it is one
+ that we opened.
+
+ Returns NULL on success.
+
+ Returns the malloc descriptor on failure, which can subsequently be used
+ for further action, such as obtaining more information about the nature of
+ the failure by examining the preserved errno value.
+
+ Note that the malloc descriptor that we are using is currently located in
+ region we are about to unmap, so we first make a local copy of it on the
+ stack and use the copy. */
+
+PTR
+mmalloc_detach (md)
+ PTR md;
+{
+ struct mdesc mtemp;
+
+ if (md != NULL)
+ {
+
+ mtemp = *(struct mdesc *) md;
+
+ /* Now unmap all the pages associated with this region by asking for a
+ negative increment equal to the current size of the region. */
+
+ if ((mtemp.morecore (&mtemp, mtemp.base - mtemp.top)) == NULL)
+ {
+ /* Update the original malloc descriptor with any changes */
+ *(struct mdesc *) md = mtemp;
+ }
+ else
+ {
+ if (mtemp.flags & MMALLOC_DEVZERO)
+ {
+ close (mtemp.fd);
+ }
+ md = NULL;
+ }
+ }
+
+ return (md);
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/keys.c b/gnu/usr.bin/gdb/mmalloc/keys.c
new file mode 100644
index 000000000000..69d41b977395
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/keys.c
@@ -0,0 +1,66 @@
+/* Access for application keys in mmap'd malloc managed region.
+ Copyright 1992 Free Software Foundation, Inc.
+
+ Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com
+
+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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* This module provides access to some keys that the application can use to
+ provide persistent access to locations in the mapped memory section.
+ The intent is that these keys are to be used sparingly as sort of
+ persistent global variables which the application can use to reinitialize
+ access to data in the mapped region.
+
+ For the moment, these keys are simply stored in the malloc descriptor
+ itself, in an array of fixed length. This should be fixed so that there
+ can be an unlimited number of keys, possibly using a multilevel access
+ scheme of some sort. */
+
+#include "mmalloc.h"
+
+int
+mmalloc_setkey (md, keynum, key)
+ PTR md;
+ int keynum;
+ PTR key;
+{
+ struct mdesc *mdp = (struct mdesc *) md;
+ int result = 0;
+
+ if ((mdp != NULL) && (keynum >= 0) && (keynum < MMALLOC_KEYS))
+ {
+ mdp -> keys [keynum] = key;
+ result++;
+ }
+ return (result);
+}
+
+PTR
+mmalloc_getkey (md, keynum)
+ PTR md;
+ int keynum;
+{
+ struct mdesc *mdp = (struct mdesc *) md;
+ PTR keyval = NULL;
+
+ if ((mdp != NULL) && (keynum >= 0) && (keynum < MMALLOC_KEYS))
+ {
+ keyval = mdp -> keys [keynum];
+ }
+ return (keyval);
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/mcalloc.c b/gnu/usr.bin/gdb/mmalloc/mcalloc.c
new file mode 100644
index 000000000000..08f07bfe1c79
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mcalloc.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1991, 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <string.h> /* Prototypes for memcpy, memmove, memset, etc */
+
+#include "mmalloc.h"
+
+/* Allocate an array of NMEMB elements each SIZE bytes long.
+ The entire array is initialized to zeros. */
+
+PTR
+mcalloc (md, nmemb, size)
+ PTR md;
+ register size_t nmemb;
+ register size_t size;
+{
+ register PTR result;
+
+ if ((result = mmalloc (md, nmemb * size)) != NULL)
+ {
+ memset (result, 0, nmemb * size);
+ }
+ return (result);
+}
+
+/* When using this package, provide a version of malloc/realloc/free built
+ on top of it, so that if we use the default sbrk() region we will not
+ collide with another malloc package trying to do the same thing, if
+ the application contains any "hidden" calls to malloc/realloc/free (such
+ as inside a system library). */
+
+PTR
+calloc (nmemb, size)
+ size_t nmemb;
+ size_t size;
+{
+ return (mcalloc ((PTR) NULL, nmemb, size));
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/mfree.c b/gnu/usr.bin/gdb/mmalloc/mfree.c
new file mode 100644
index 000000000000..aee43aad15bf
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mfree.c
@@ -0,0 +1,247 @@
+/* Free a block of memory allocated by `mmalloc'.
+ Copyright 1990, 1991, 1992 Free Software Foundation
+
+ Written May 1989 by Mike Haertel.
+ Heavily modified Mar 1992 by Fred Fish. (fnf@cygnus.com)
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. 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 "mmalloc.h"
+
+/* Return memory to the heap.
+ Like `mfree' but don't call a mfree_hook if there is one. */
+
+void
+__mmalloc_free (mdp, ptr)
+ struct mdesc *mdp;
+ PTR ptr;
+{
+ int type;
+ size_t block, blocks;
+ register size_t i;
+ struct list *prev, *next;
+
+ block = BLOCK (ptr);
+
+ type = mdp -> heapinfo[block].busy.type;
+ switch (type)
+ {
+ case 0:
+ /* Get as many statistics as early as we can. */
+ mdp -> heapstats.chunks_used--;
+ mdp -> heapstats.bytes_used -=
+ mdp -> heapinfo[block].busy.info.size * BLOCKSIZE;
+ mdp -> heapstats.bytes_free +=
+ mdp -> 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 = mdp -> heapindex;
+ if (i > block)
+ {
+ while (i > block)
+ {
+ i = mdp -> heapinfo[i].free.prev;
+ }
+ }
+ else
+ {
+ do
+ {
+ i = mdp -> heapinfo[i].free.next;
+ }
+ while ((i != 0) && (i < block));
+ i = mdp -> heapinfo[i].free.prev;
+ }
+
+ /* Determine how to link this block into the free list. */
+ if (block == i + mdp -> heapinfo[i].free.size)
+ {
+ /* Coalesce this block with its predecessor. */
+ mdp -> heapinfo[i].free.size +=
+ mdp -> heapinfo[block].busy.info.size;
+ block = i;
+ }
+ else
+ {
+ /* Really link this block back into the free list. */
+ mdp -> heapinfo[block].free.size =
+ mdp -> heapinfo[block].busy.info.size;
+ mdp -> heapinfo[block].free.next = mdp -> heapinfo[i].free.next;
+ mdp -> heapinfo[block].free.prev = i;
+ mdp -> heapinfo[i].free.next = block;
+ mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
+ mdp -> heapstats.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 + mdp -> heapinfo[block].free.size ==
+ mdp -> heapinfo[block].free.next)
+ {
+ mdp -> heapinfo[block].free.size
+ += mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.size;
+ mdp -> heapinfo[block].free.next
+ = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.next;
+ mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev = block;
+ mdp -> heapstats.chunks_free--;
+ }
+
+ /* Now see if we can return stuff to the system. */
+ blocks = mdp -> heapinfo[block].free.size;
+ if (blocks >= FINAL_FREE_BLOCKS && block + blocks == mdp -> heaplimit
+ && mdp -> morecore (mdp, 0) == ADDRESS (block + blocks))
+ {
+ register size_t bytes = blocks * BLOCKSIZE;
+ mdp -> heaplimit -= blocks;
+ mdp -> morecore (mdp, -bytes);
+ mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
+ = mdp -> heapinfo[block].free.next;
+ mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
+ = mdp -> heapinfo[block].free.prev;
+ block = mdp -> heapinfo[block].free.prev;
+ mdp -> heapstats.chunks_free--;
+ mdp -> heapstats.bytes_free -= bytes;
+ }
+
+ /* Set the next search to begin at this block. */
+ mdp -> heapindex = block;
+ break;
+
+ default:
+ /* Do some of the statistics. */
+ mdp -> heapstats.chunks_used--;
+ mdp -> heapstats.bytes_used -= 1 << type;
+ mdp -> heapstats.chunks_free++;
+ mdp -> heapstats.bytes_free += 1 << type;
+
+ /* Get the address of the first free fragment in this block. */
+ prev = (struct list *)
+ ((char *) ADDRESS(block) +
+ (mdp -> heapinfo[block].busy.info.frag.first << type));
+
+ if (mdp -> 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 < (size_t) (BLOCKSIZE >> type); ++i)
+ {
+ next = next -> next;
+ }
+ prev -> prev -> next = next;
+ if (next != NULL)
+ {
+ next -> prev = prev -> prev;
+ }
+ mdp -> heapinfo[block].busy.type = 0;
+ mdp -> heapinfo[block].busy.info.size = 1;
+
+ /* Keep the statistics accurate. */
+ mdp -> heapstats.chunks_used++;
+ mdp -> heapstats.bytes_used += BLOCKSIZE;
+ mdp -> heapstats.chunks_free -= BLOCKSIZE >> type;
+ mdp -> heapstats.bytes_free -= BLOCKSIZE;
+
+ mfree ((PTR) mdp, (PTR) ADDRESS(block));
+ }
+ else if (mdp -> 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;
+ }
+ ++mdp -> 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;
+ mdp -> heapinfo[block].busy.info.frag.nfree = 1;
+ mdp -> heapinfo[block].busy.info.frag.first =
+ RESIDUAL (ptr, BLOCKSIZE) >> type;
+ prev -> next = mdp -> fraghead[type].next;
+ prev -> prev = &mdp -> fraghead[type];
+ prev -> prev -> next = prev;
+ if (prev -> next != NULL)
+ {
+ prev -> next -> prev = prev;
+ }
+ }
+ break;
+ }
+}
+
+/* Return memory to the heap. */
+
+void
+mfree (md, ptr)
+ PTR md;
+ PTR ptr;
+{
+ struct mdesc *mdp;
+ register struct alignlist *l;
+
+ if (ptr != NULL)
+ {
+ mdp = MD_TO_MDP (md);
+ for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)
+ {
+ if (l -> aligned == ptr)
+ {
+ l -> aligned = NULL; /* Mark the slot in the list as free. */
+ ptr = l -> exact;
+ break;
+ }
+ }
+ if (mdp -> mfree_hook != NULL)
+ {
+ (*mdp -> mfree_hook) (md, ptr);
+ }
+ else
+ {
+ __mmalloc_free (mdp, ptr);
+ }
+ }
+}
+
+/* When using this package, provide a version of malloc/realloc/free built
+ on top of it, so that if we use the default sbrk() region we will not
+ collide with another malloc package trying to do the same thing, if
+ the application contains any "hidden" calls to malloc/realloc/free (such
+ as inside a system library). */
+
+void
+free (ptr)
+ PTR ptr;
+{
+ mfree ((PTR) NULL, ptr);
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/mmalloc.c b/gnu/usr.bin/gdb/mmalloc/mmalloc.c
new file mode 100644
index 000000000000..46b450e8513d
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mmalloc.c
@@ -0,0 +1,334 @@
+/* Memory allocator `malloc'.
+ Copyright 1990, 1991, 1992 Free Software Foundation
+
+ Written May 1989 by Mike Haertel.
+ Heavily modified Mar 1992 by Fred Fish for mmap'd version.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. 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 <string.h> /* Prototypes for memcpy, memmove, memset, etc */
+
+#include "mmalloc.h"
+
+/* Prototypes for local functions */
+
+static int initialize PARAMS ((struct mdesc *));
+static PTR morecore PARAMS ((struct mdesc *, size_t));
+static PTR align PARAMS ((struct mdesc *, size_t));
+
+/* Aligned allocation. */
+
+static PTR
+align (mdp, size)
+ struct mdesc *mdp;
+ size_t size;
+{
+ PTR result;
+ unsigned long int adj;
+
+ result = mdp -> morecore (mdp, size);
+ adj = RESIDUAL (result, BLOCKSIZE);
+ if (adj != 0)
+ {
+ adj = BLOCKSIZE - adj;
+ mdp -> morecore (mdp, adj);
+ result = (char *) result + adj;
+ }
+ return (result);
+}
+
+/* Set everything up and remember that we have. */
+
+static int
+initialize (mdp)
+ struct mdesc *mdp;
+{
+ mdp -> heapsize = HEAP / BLOCKSIZE;
+ mdp -> heapinfo = (malloc_info *)
+ align (mdp, mdp -> heapsize * sizeof (malloc_info));
+ if (mdp -> heapinfo == NULL)
+ {
+ return (0);
+ }
+ memset ((PTR)mdp -> heapinfo, 0, mdp -> heapsize * sizeof (malloc_info));
+ mdp -> heapinfo[0].free.size = 0;
+ mdp -> heapinfo[0].free.next = mdp -> heapinfo[0].free.prev = 0;
+ mdp -> heapindex = 0;
+ mdp -> heapbase = (char *) mdp -> heapinfo;
+ mdp -> flags |= MMALLOC_INITIALIZED;
+ return (1);
+}
+
+/* Get neatly aligned memory, initializing or
+ growing the heap info table as necessary. */
+
+static PTR
+morecore (mdp, size)
+ struct mdesc *mdp;
+ size_t size;
+{
+ PTR result;
+ malloc_info *newinfo, *oldinfo;
+ size_t newsize;
+
+ result = align (mdp, size);
+ if (result == NULL)
+ {
+ return (NULL);
+ }
+
+ /* Check if we need to grow the info table. */
+ if ((size_t) BLOCK ((char *) result + size) > mdp -> heapsize)
+ {
+ newsize = mdp -> heapsize;
+ while ((size_t) BLOCK ((char *) result + size) > newsize)
+ {
+ newsize *= 2;
+ }
+ newinfo = (malloc_info *) align (mdp, newsize * sizeof (malloc_info));
+ if (newinfo == NULL)
+ {
+ mdp -> morecore (mdp, -size);
+ return (NULL);
+ }
+ memset ((PTR) newinfo, 0, newsize * sizeof (malloc_info));
+ memcpy ((PTR) newinfo, (PTR) mdp -> heapinfo,
+ mdp -> heapsize * sizeof (malloc_info));
+ oldinfo = mdp -> heapinfo;
+ newinfo[BLOCK (oldinfo)].busy.type = 0;
+ newinfo[BLOCK (oldinfo)].busy.info.size
+ = BLOCKIFY (mdp -> heapsize * sizeof (malloc_info));
+ mdp -> heapinfo = newinfo;
+ __mmalloc_free (mdp, (PTR)oldinfo);
+ mdp -> heapsize = newsize;
+ }
+
+ mdp -> heaplimit = BLOCK ((char *) result + size);
+ return (result);
+}
+
+/* Allocate memory from the heap. */
+
+PTR
+mmalloc (md, size)
+ PTR md;
+ size_t size;
+{
+ struct mdesc *mdp;
+ PTR result;
+ size_t block, blocks, lastblocks, start;
+ register size_t i;
+ struct list *next;
+ register size_t log;
+
+ if (size == 0)
+ {
+ return (NULL);
+ }
+
+ mdp = MD_TO_MDP (md);
+
+ if (mdp -> mmalloc_hook != NULL)
+ {
+ return ((*mdp -> mmalloc_hook) (md, size));
+ }
+
+ if (!(mdp -> flags & MMALLOC_INITIALIZED))
+ {
+ if (!initialize (mdp))
+ {
+ 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. */
+ log = 1;
+ --size;
+ while ((size /= 2) != 0)
+ {
+ ++log;
+ }
+
+ /* Look in the fragment lists for a
+ free fragment of the desired size. */
+ next = mdp -> 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 (--mdp -> heapinfo[block].busy.info.frag.nfree != 0)
+ {
+ mdp -> heapinfo[block].busy.info.frag.first =
+ RESIDUAL (next -> next, BLOCKSIZE) >> log;
+ }
+
+ /* Update the statistics. */
+ mdp -> heapstats.chunks_used++;
+ mdp -> heapstats.bytes_used += 1 << log;
+ mdp -> heapstats.chunks_free--;
+ mdp -> heapstats.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 = mmalloc (md, BLOCKSIZE);
+ if (result == NULL)
+ {
+ return (NULL);
+ }
+
+ /* Link all fragments but the first into the free list. */
+ for (i = 1; i < (size_t) (BLOCKSIZE >> log); ++i)
+ {
+ next = (struct list *) ((char *) result + (i << log));
+ next -> next = mdp -> fraghead[log].next;
+ next -> prev = &mdp -> 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);
+ mdp -> heapinfo[block].busy.type = log;
+ mdp -> heapinfo[block].busy.info.frag.nfree = i - 1;
+ mdp -> heapinfo[block].busy.info.frag.first = i - 1;
+
+ mdp -> heapstats.chunks_free += (BLOCKSIZE >> log) - 1;
+ mdp -> heapstats.bytes_free += BLOCKSIZE - (1 << log);
+ mdp -> heapstats.bytes_used -= 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 (mdp -> heapinfo[block].free.size < blocks)
+ {
+ block = mdp -> 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 = mdp -> heapinfo[0].free.prev;
+ lastblocks = mdp -> heapinfo[block].free.size;
+ if (mdp -> heaplimit != 0 &&
+ block + lastblocks == mdp -> heaplimit &&
+ mdp -> morecore (mdp, 0) == ADDRESS(block + lastblocks) &&
+ (morecore (mdp, (blocks - lastblocks) * BLOCKSIZE)) != NULL)
+ {
+ /* Which block we are extending (the `final free
+ block' referred to above) might have changed, if
+ it got combined with a freed info table. */
+ block = mdp -> heapinfo[0].free.prev;
+
+ mdp -> heapinfo[block].free.size += (blocks - lastblocks);
+ mdp -> heapstats.bytes_free +=
+ (blocks - lastblocks) * BLOCKSIZE;
+ continue;
+ }
+ result = morecore(mdp, blocks * BLOCKSIZE);
+ if (result == NULL)
+ {
+ return (NULL);
+ }
+ block = BLOCK (result);
+ mdp -> heapinfo[block].busy.type = 0;
+ mdp -> heapinfo[block].busy.info.size = blocks;
+ mdp -> heapstats.chunks_used++;
+ mdp -> heapstats.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 (mdp -> heapinfo[block].free.size > blocks)
+ {
+ /* The block we found has a bit left over,
+ so relink the tail end back into the free list. */
+ mdp -> heapinfo[block + blocks].free.size
+ = mdp -> heapinfo[block].free.size - blocks;
+ mdp -> heapinfo[block + blocks].free.next
+ = mdp -> heapinfo[block].free.next;
+ mdp -> heapinfo[block + blocks].free.prev
+ = mdp -> heapinfo[block].free.prev;
+ mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
+ = mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
+ = mdp -> heapindex = block + blocks;
+ }
+ else
+ {
+ /* The block exactly matches our requirements,
+ so just remove it from the list. */
+ mdp -> heapinfo[mdp -> heapinfo[block].free.next].free.prev
+ = mdp -> heapinfo[block].free.prev;
+ mdp -> heapinfo[mdp -> heapinfo[block].free.prev].free.next
+ = mdp -> heapindex = mdp -> heapinfo[block].free.next;
+ mdp -> heapstats.chunks_free--;
+ }
+
+ mdp -> heapinfo[block].busy.type = 0;
+ mdp -> heapinfo[block].busy.info.size = blocks;
+ mdp -> heapstats.chunks_used++;
+ mdp -> heapstats.bytes_used += blocks * BLOCKSIZE;
+ mdp -> heapstats.bytes_free -= blocks * BLOCKSIZE;
+ }
+
+ return (result);
+}
+
+/* When using this package, provide a version of malloc/realloc/free built
+ on top of it, so that if we use the default sbrk() region we will not
+ collide with another malloc package trying to do the same thing, if
+ the application contains any "hidden" calls to malloc/realloc/free (such
+ as inside a system library). */
+
+PTR
+malloc (size)
+ size_t size;
+{
+ return (mmalloc ((PTR) NULL, size));
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/mmalloc.h b/gnu/usr.bin/gdb/mmalloc/mmalloc.h
new file mode 100644
index 000000000000..54b6ed654dcd
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mmalloc.h
@@ -0,0 +1,390 @@
+/* Declarations for `mmalloc' and friends.
+ Copyright 1990, 1991, 1992 Free Software Foundation
+
+ Written May 1989 by Mike Haertel.
+ Heavily modified Mar 1992 by Fred Fish. (fnf@cygnus.com)
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. 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 __MMALLOC_H
+#define __MMALLOC_H 1
+
+#ifdef __STDC__
+# include <stddef.h>
+# define PTR void *
+# define CONST const
+# define PARAMS(paramlist) paramlist
+# include <limits.h>
+# ifndef NULL
+# define NULL (void *) 0
+# endif
+#else
+# define PTR char *
+# define CONST /* nothing */
+# define PARAMS(paramlist) ()
+# ifndef size_t
+# define size_t unsigned int
+# endif
+# ifndef CHAR_BIT
+# define CHAR_BIT 8
+# endif
+# ifndef NULL
+# define NULL 0
+# endif
+#endif
+
+#ifndef MIN
+# define MIN(A, B) ((A) < (B) ? (A) : (B))
+#endif
+
+#define MMALLOC_MAGIC "mmalloc" /* Mapped file magic number */
+#define MMALLOC_MAGIC_SIZE 8 /* Size of magic number buf */
+#define MMALLOC_VERSION 1 /* Current mmalloc version */
+#define MMALLOC_KEYS 16 /* Keys for application use */
+
+/* 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 ((unsigned int) 1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* The difference between two pointers is a signed int. On machines where
+ the data addresses have the high bit set, we need to ensure that the
+ difference becomes an unsigned int when we are using the address as an
+ integral value. In addition, when using with the '%' operator, the
+ sign of the result is machine dependent for negative values, so force
+ it to be treated as an unsigned int. */
+
+#define ADDR2UINT(addr) ((unsigned int) ((char *) (addr) - (char *) NULL))
+#define RESIDUAL(addr,bsize) ((unsigned int) (ADDR2UINT (addr) % (bsize)))
+
+/* 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 mdp -> heapindex
+
+/* Address to block number and vice versa. */
+
+#define BLOCK(A) (((char *) (A) - mdp -> heapbase) / BLOCKSIZE + 1)
+
+#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + mdp -> heapbase))
+
+/* 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;
+
+/* List of blocks allocated with `mmemalign' (or `mvalloc'). */
+
+struct alignlist
+ {
+ struct alignlist *next;
+ PTR aligned; /* The address that mmemaligned returned. */
+ PTR exact; /* The address that malloc returned. */
+ };
+
+/* Doubly linked lists of free fragments. */
+
+struct list
+ {
+ struct list *next;
+ struct list *prev;
+ };
+
+/* Statistics available to the user.
+ FIXME: By design, the internals of the malloc package are no longer
+ exported to the user via an include file, so access to this data needs
+ to be via some other mechanism, such as mmstat_<something> where the
+ return value is the <something> the user is interested in. */
+
+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. */
+ };
+
+/* Internal structure that defines the format of the malloc-descriptor.
+ This gets written to the base address of the region that mmalloc is
+ managing, and thus also becomes the file header for the mapped file,
+ if such a file exists. */
+
+struct mdesc
+{
+ /* The "magic number" for an mmalloc file. */
+
+ char magic[MMALLOC_MAGIC_SIZE];
+
+ /* The size in bytes of this structure, used as a sanity check when reusing
+ a previously created mapped file. */
+
+ unsigned int headersize;
+
+ /* The version number of the mmalloc package that created this file. */
+
+ unsigned char version;
+
+ /* Some flag bits to keep track of various internal things. */
+
+ unsigned int flags;
+
+ /* If a system call made by the mmalloc package fails, the errno is
+ preserved for future examination. */
+
+ int saved_errno;
+
+ /* Pointer to the function that is used to get more core, or return core
+ to the system, for requests using this malloc descriptor. For memory
+ mapped regions, this is the mmap() based routine. There may also be
+ a single malloc descriptor that points to an sbrk() based routine
+ for systems without mmap() or for applications that call the mmalloc()
+ package with a NULL malloc descriptor.
+
+ FIXME: For mapped regions shared by more than one process, this
+ needs to be maintained on a per-process basis. */
+
+ PTR (*morecore) PARAMS ((struct mdesc *, int));
+
+ /* Pointer to the function that causes an abort when the memory checking
+ features are activated. By default this is set to abort(), but can
+ be set to another function by the application using mmalloc().
+
+ FIXME: For mapped regions shared by more than one process, this
+ needs to be maintained on a per-process basis. */
+
+ void (*abortfunc) PARAMS ((void));
+
+ /* Debugging hook for free.
+
+ FIXME: For mapped regions shared by more than one process, this
+ needs to be maintained on a per-process basis. */
+
+ void (*mfree_hook) PARAMS ((PTR, PTR));
+
+ /* Debugging hook for `malloc'.
+
+ FIXME: For mapped regions shared by more than one process, this
+ needs to be maintained on a per-process basis. */
+
+ PTR (*mmalloc_hook) PARAMS ((PTR, size_t));
+
+ /* Debugging hook for realloc.
+
+ FIXME: For mapped regions shared by more than one process, this
+ needs to be maintained on a per-process basis. */
+
+ PTR (*mrealloc_hook) PARAMS ((PTR, PTR, size_t));
+
+ /* Number of info entries. */
+
+ size_t heapsize;
+
+ /* Pointer to first block of the heap (base of the first block). */
+
+ char *heapbase;
+
+ /* Current search index for the heap table. */
+ /* Search index in the info table. */
+
+ size_t heapindex;
+
+ /* Limit of valid info table indices. */
+
+ size_t heaplimit;
+
+ /* Block information table.
+ Allocated with malign/__mmalloc_free (not mmalloc/mfree). */
+ /* Table indexed by block number giving per-block information. */
+
+ malloc_info *heapinfo;
+
+ /* Instrumentation. */
+
+ struct mstats heapstats;
+
+ /* Free list headers for each fragment size. */
+ /* Free lists for each fragment size. */
+
+ struct list fraghead[BLOCKLOG];
+
+ /* List of blocks allocated by memalign. */
+
+ struct alignlist *aligned_blocks;
+
+ /* The base address of the memory region for this malloc heap. This
+ is the location where the bookkeeping data for mmap and for malloc
+ begins. */
+
+ char *base;
+
+ /* The current location in the memory region for this malloc heap which
+ represents the end of memory in use. */
+
+ char *breakval;
+
+ /* The end of the current memory region for this malloc heap. This is
+ the first location past the end of mapped memory. */
+
+ char *top;
+
+ /* Open file descriptor for the file to which this malloc heap is mapped.
+ This will always be a valid file descriptor, since /dev/zero is used
+ by default if no open file is supplied by the client. Also note that
+ it may change each time the region is mapped and unmapped. */
+
+ int fd;
+
+ /* An array of keys to data within the mapped region, for use by the
+ application. */
+
+ PTR keys[MMALLOC_KEYS];
+
+};
+
+/* Bits to look at in the malloc descriptor flags word */
+
+#define MMALLOC_DEVZERO (1 << 0) /* Have mapped to /dev/zero */
+#define MMALLOC_INITIALIZED (1 << 1) /* Initialized mmalloc */
+#define MMALLOC_MMCHECK_USED (1 << 2) /* mmcheck() called already */
+
+/* Allocate SIZE bytes of memory. */
+
+extern PTR mmalloc PARAMS ((PTR, size_t));
+
+/* Re-allocate the previously allocated block in PTR, making the new block
+ SIZE bytes long. */
+
+extern PTR mrealloc PARAMS ((PTR, PTR, size_t));
+
+/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */
+
+extern PTR mcalloc PARAMS ((PTR, size_t, size_t));
+
+/* Free a block allocated by `mmalloc', `mrealloc' or `mcalloc'. */
+
+extern void mfree PARAMS ((PTR, PTR));
+
+/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
+
+extern PTR mmemalign PARAMS ((PTR, size_t, size_t));
+
+/* Allocate SIZE bytes on a page boundary. */
+
+extern PTR mvalloc PARAMS ((PTR, size_t));
+
+/* Activate a standard collection of debugging hooks. */
+
+extern int mmcheck PARAMS ((PTR, void (*) (void)));
+
+/* Pick up the current statistics. (see FIXME elsewhere) */
+
+extern struct mstats mmstats PARAMS ((PTR));
+
+/* Internal version of `mfree' used in `morecore'. */
+
+extern void __mmalloc_free PARAMS ((struct mdesc *, PTR));
+
+/* Hooks for debugging versions. */
+
+extern void (*__mfree_hook) PARAMS ((PTR, PTR));
+extern PTR (*__mmalloc_hook) PARAMS ((PTR, size_t));
+extern PTR (*__mrealloc_hook) PARAMS ((PTR, PTR, size_t));
+
+/* A default malloc descriptor for the single sbrk() managed region. */
+
+extern struct mdesc *__mmalloc_default_mdp;
+
+/* Initialize the first use of the default malloc descriptor, which uses
+ an sbrk() region. */
+
+extern struct mdesc *__mmalloc_sbrk_init PARAMS ((void));
+
+/* Grow or shrink a contiguous mapped region using mmap().
+ Works much like sbrk() */
+
+#if defined(HAVE_MMAP)
+
+extern PTR __mmalloc_mmap_morecore PARAMS ((struct mdesc *, int));
+
+#endif
+
+/* Remap a mmalloc region that was previously mapped. */
+
+extern PTR __mmalloc_remap_core PARAMS ((struct mdesc *));
+
+/* Macro to convert from a user supplied malloc descriptor to pointer to the
+ internal malloc descriptor. If the user supplied descriptor is NULL, then
+ use the default internal version, initializing it if necessary. Otherwise
+ just cast the user supplied version (which is void *) to the proper type
+ (struct mdesc *). */
+
+#define MD_TO_MDP(md) \
+ ((md) == NULL \
+ ? (__mmalloc_default_mdp == NULL \
+ ? __mmalloc_sbrk_init () \
+ : __mmalloc_default_mdp) \
+ : (struct mdesc *) (md))
+
+#endif /* __MMALLOC_H */
diff --git a/gnu/usr.bin/gdb/mmalloc/mmalloc.texi b/gnu/usr.bin/gdb/mmalloc/mmalloc.texi
new file mode 100644
index 000000000000..f70ae68621ee
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mmalloc.texi
@@ -0,0 +1,258 @@
+\input texinfo @c -*- Texinfo -*-
+@setfilename mmalloc.info
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Mmalloc: (mmalloc). The GNU mapped-malloc package.
+END-INFO-DIR-ENTRY
+@end format
+
+This file documents the GNU mmalloc (mapped-malloc) package, written by
+fnf@@cygnus.com, based on GNU malloc written by mike@@ai.mit.edu.
+
+Copyright (C) 1992 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
+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
+@iftex
+@c @finalout
+@setchapternewpage odd
+@settitle MMALLOC, the GNU memory-mapped malloc package
+@titlepage
+@title mmalloc
+@subtitle The GNU memory-mapped malloc package
+@author Fred Fish
+@author Cygnus Support
+@author Mike Haertel
+@author Free Software Foundation
+@page
+
+@tex
+\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision: 1.1 $} % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill fnf\@cygnus.com\par
+\hfill {\it MMALLOC, the GNU memory-mapped malloc package}, \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+@end iftex
+
+@ifinfo
+@node Top, Overview, (dir), (dir)
+@top mmalloc
+This file documents the GNU memory-mapped malloc package mmalloc.
+
+@menu
+* Overview:: Overall Description
+* Implementation:: Implementation
+
+ --- The Detailed Node Listing ---
+
+Implementation
+
+* Compatibility:: Backwards Compatibility
+* Functions:: Function Descriptions
+@end menu
+
+@end ifinfo
+
+@node Overview, Implementation, Top, Top
+@chapter Overall Description
+
+This is a heavily modified version of GNU @code{malloc}. It uses
+@code{mmap} as the basic mechanism for for obtaining memory from the
+system, rather than @code{sbrk}. This gives it several advantages over the
+more traditional malloc:
+
+@itemize @bullet
+@item
+Several different heaps can be used, each of them growing
+or shinking under control of @code{mmap}, with the @code{mmalloc} functions
+using a specific heap on a call by call basis.
+
+@item
+By using @code{mmap}, it is easy to create heaps which are intended to
+be persistent and exist as a filesystem object after the creating
+process has gone away.
+
+@item
+Because multiple heaps can be managed, data used for a
+specific purpose can be allocated into its own heap, making
+it easier to allow applications to ``dump'' and ``restore'' initialized
+malloc-managed memory regions. For example, the ``unexec'' hack popularized
+by GNU Emacs could potentially go away.
+@end itemize
+
+@node Implementation, , Overview, Top
+@chapter Implementation
+
+The @code{mmalloc} functions contain no internal static state. All
+@code{mmalloc} internal data is allocated in the mapped in region, along
+with the user data that it manages. This allows it to manage multiple
+such regions and to ``pick up where it left off'' when such regions are
+later dynamically mapped back in.
+
+In some sense, malloc has been ``purified'' to contain no internal state
+information and generalized to use multiple memory regions rather than a
+single region managed by @code{sbrk}. However the new routines now need an
+extra parameter which informs @code{mmalloc} which memory region it is dealing
+with (along with other information). This parameter is called the
+@dfn{malloc descriptor}.
+
+The functions initially provided by @code{mmalloc} are:
+
+@example
+void *mmalloc_attach (int fd, void *baseaddr);
+void *mmalloc_detach (void *md);
+int mmalloc_errno (void *md);
+int mmalloc_setkey (void *md, int keynum, void *key);
+void *mmalloc_getkey (void *md, int keynum);
+
+void *mmalloc (void *md, size_t size);
+void *mrealloc (void *md, void *ptr, size_t size);
+void *mvalloc (void *md, size_t size);
+void mfree (void *md, void *ptr);
+@end example
+
+@menu
+* Compatibility:: Backwards Compatibility
+* Functions:: Function Descriptions
+@end menu
+
+@node Compatibility, Functions, Implementation, Implementation
+@section Backwards Compatibility
+
+To allow a single malloc package to be used in a given application,
+provision is made for the traditional @code{malloc}, @code{realloc}, and
+@code{free} functions to be implemented as special cases of the
+@code{mmalloc} functions. In particular, if any of the functions that
+expect malloc descriptors are called with a @code{NULL} pointer rather than a
+valid malloc descriptor, then they default to using an @code{sbrk} managed
+region.
+The @code{mmalloc} package provides compatible @code{malloc}, @code{realloc},
+and @code{free} functions using this mechanism internally.
+Applications can avoid this extra interface layer by simply including the
+following defines:
+
+@example
+#define malloc(size) mmalloc ((void *)0, (size))
+#define realloc(ptr,size) mrealloc ((void *)0, (ptr), (size));
+#define free(ptr) mfree ((void *)0, (ptr))
+@end example
+
+@noindent
+or replace the existing @code{malloc}, @code{realloc}, and @code{free}
+calls with the above patterns if using @code{#define} causes problems.
+
+@node Functions, , Compatibility, Implementation
+@section Function Descriptions
+
+These are the details on the functions that make up the @code{mmalloc}
+package.
+
+@table @code
+@item void *mmalloc_attach (int @var{fd}, void *@var{baseaddr});
+Initialize access to a @code{mmalloc} managed region.
+
+If @var{fd} is a valid file descriptor for an open file, then data for the
+@code{mmalloc} managed region is mapped to that file. Otherwise
+@file{/dev/zero} is used and the data will not exist in any filesystem object.
+
+If the open file corresponding to @var{fd} is from a previous use of
+@code{mmalloc} and passes some basic sanity checks to ensure that it is
+compatible with the current @code{mmalloc} package, then its data is
+mapped in and is immediately accessible at the same addresses in
+the current process as the process that created the file.
+
+If @var{baseaddr} is not @code{NULL}, the mapping is established
+starting at the specified address in the process address space. If
+@var{baseaddr} is @code{NULL}, the @code{mmalloc} package chooses a
+suitable address at which to start the mapped region, which will be the
+value of the previous mapping if opening an existing file which was
+previously built by @code{mmalloc}, or for new files will be a value
+chosen by @code{mmap}.
+
+Specifying @var{baseaddr} provides more control over where the regions
+start and how big they can be before bumping into existing mapped
+regions or future mapped regions.
+
+On success, returns a malloc descriptor which is used in subsequent
+calls to other @code{mmalloc} package functions. It is explicitly
+@samp{void *} (@samp{char *} for systems that don't fully support
+@code{void}) so that users of the package don't have to worry about the
+actual implementation details.
+
+On failure returns @code{NULL}.
+
+@item void *mmalloc_detach (void *@var{md});
+Terminate access to a @code{mmalloc} managed region identified by the
+descriptor @var{md}, by closing the base file and unmapping all memory
+pages associated with the region.
+
+Returns @code{NULL} on success.
+
+Returns the malloc descriptor on failure, which can subsequently
+be used for further action (such as obtaining more information about
+the nature of the failure).
+
+@item void *mmalloc (void *@var{md}, size_t @var{size});
+Given an @code{mmalloc} descriptor @var{md}, allocate additional memory of
+@var{size} bytes in the associated mapped region.
+
+@item *mrealloc (void *@var{md}, void *@var{ptr}, size_t @var{size});
+Given an @code{mmalloc} descriptor @var{md} and a pointer to memory
+previously allocated by @code{mmalloc} in @var{ptr}, reallocate the
+memory to be @var{size} bytes long, possibly moving the existing
+contents of memory if necessary.
+
+@item void *mvalloc (void *@var{md}, size_t @var{size});
+Like @code{mmalloc} but the resulting memory is aligned on a page boundary.
+
+@item void mfree (void *@var{md}, void *@var{ptr});
+Given an @code{mmalloc} descriptor @var{md} and a pointer to memory previously
+allocated by @code{mmalloc} in @var{ptr}, free the previously allocated memory.
+
+@item int mmalloc_errno (void *@var{md});
+Given a @code{mmalloc} descriptor, if the last @code{mmalloc} operation
+failed for some reason due to a system call failure, then
+returns the associated @code{errno}. Returns 0 otherwise.
+(This function is not yet implemented).
+@end table
+
+@bye
diff --git a/gnu/usr.bin/gdb/mmalloc/mmap-sup.c b/gnu/usr.bin/gdb/mmalloc/mmap-sup.c
new file mode 100644
index 000000000000..37b307905c5b
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mmap-sup.c
@@ -0,0 +1,144 @@
+/* Support for an sbrk-like function that uses mmap.
+ Copyright 1992 Free Software Foundation, Inc.
+
+ Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com
+
+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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#if defined(HAVE_MMAP)
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#include "mmalloc.h"
+
+extern int munmap PARAMS ((caddr_t, size_t)); /* Not in any header file */
+
+/* Cache the pagesize for the current host machine. Note that if the host
+ does not readily provide a getpagesize() function, we need to emulate it
+ elsewhere, not clutter up this file with lots of kluges to try to figure
+ it out. */
+
+static size_t pagesize;
+extern int getpagesize PARAMS ((void));
+
+#define PAGE_ALIGN(addr) (caddr_t) (((long)(addr) + pagesize - 1) & \
+ ~(pagesize - 1))
+
+/* Get core for the memory region specified by MDP, using SIZE as the
+ amount to either add to or subtract from the existing region. Works
+ like sbrk(), but using mmap(). */
+
+PTR
+__mmalloc_mmap_morecore (mdp, size)
+ struct mdesc *mdp;
+ int size;
+{
+ PTR result = NULL;
+ off_t foffset; /* File offset at which new mapping will start */
+ size_t mapbytes; /* Number of bytes to map */
+ caddr_t moveto; /* Address where we wish to move "break value" to */
+ caddr_t mapto; /* Address we actually mapped to */
+ char buf = 0; /* Single byte to write to extend mapped file */
+
+ if (pagesize == 0)
+ {
+ pagesize = getpagesize ();
+ }
+ if (size == 0)
+ {
+ /* Just return the current "break" value. */
+ result = mdp -> breakval;
+ }
+ else if (size < 0)
+ {
+ /* We are deallocating memory. If the amount requested would cause
+ us to try to deallocate back past the base of the mmap'd region
+ then do nothing, and return NULL. Otherwise, deallocate the
+ memory and return the old break value. */
+ if (mdp -> breakval + size >= mdp -> base)
+ {
+ result = (PTR) mdp -> breakval;
+ mdp -> breakval += size;
+ moveto = PAGE_ALIGN (mdp -> breakval);
+ munmap (moveto, (size_t) (mdp -> top - moveto));
+ mdp -> top = moveto;
+ }
+ }
+ else
+ {
+ /* We are allocating memory. Make sure we have an open file
+ descriptor and then go on to get the memory. */
+ if (mdp -> fd < 0)
+ {
+ result = NULL;
+ }
+ else if (mdp -> breakval + size > mdp -> top)
+ {
+ /* The request would move us past the end of the currently
+ mapped memory, so map in enough more memory to satisfy
+ the request. This means we also have to grow the mapped-to
+ file by an appropriate amount, since mmap cannot be used
+ to extend a file. */
+ moveto = PAGE_ALIGN (mdp -> breakval + size);
+ mapbytes = moveto - mdp -> top;
+ foffset = mdp -> top - mdp -> base;
+ /* FIXME: Test results of lseek() and write() */
+ lseek (mdp -> fd, foffset + mapbytes - 1, SEEK_SET);
+ write (mdp -> fd, &buf, 1);
+ mapto = mmap (mdp -> top, mapbytes, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED, mdp -> fd, foffset);
+ if (mapto == mdp -> top)
+ {
+ mdp -> top = moveto;
+ result = (PTR) mdp -> breakval;
+ mdp -> breakval += size;
+ }
+ }
+ else
+ {
+ result = (PTR) mdp -> breakval;
+ mdp -> breakval += size;
+ }
+ }
+ return (result);
+}
+
+PTR
+__mmalloc_remap_core (mdp)
+ struct mdesc *mdp;
+{
+ caddr_t base;
+
+ /* FIXME: Quick hack, needs error checking and other attention. */
+
+ base = mmap (mdp -> base, mdp -> top - mdp -> base,
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
+ mdp -> fd, 0);
+ return ((PTR) base);
+}
+
+#else /* defined(HAVE_MMAP) */
+/* Prevent "empty translation unit" warnings from the idiots at X3J11. */
+static char ansi_c_idiots = 69;
+#endif /* defined(HAVE_MMAP) */
diff --git a/gnu/usr.bin/gdb/mmalloc/mmcheck.c b/gnu/usr.bin/gdb/mmalloc/mmcheck.c
new file mode 100644
index 000000000000..c3e29d3b3d75
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mmcheck.c
@@ -0,0 +1,196 @@
+/* Standard debugging hooks for `mmalloc'.
+ Copyright 1990, 1991, 1992 Free Software Foundation
+
+ Written May 1989 by Mike Haertel.
+ Heavily modified Mar 1992 by Fred Fish (fnf@cygnus.com)
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. 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 "mmalloc.h"
+
+/* Default function to call when something awful happens. The application
+ can specify an alternate function to be called instead (and probably will
+ want to). */
+
+extern void abort PARAMS ((void));
+
+/* Arbitrary magical numbers. */
+
+#define MAGICWORD (unsigned int) 0xfedabeeb /* Active chunk */
+#define MAGICWORDFREE (unsigned int) 0xdeadbeef /* Inactive chunk */
+#define MAGICBYTE ((char) 0xd7)
+
+/* Each memory allocation is bounded by a header structure and a trailer
+ byte. I.E.
+
+ <size><magicword><user's allocation><magicbyte>
+
+ The pointer returned to the user points to the first byte in the
+ user's allocation area. The magic word can be tested to detect
+ buffer underruns and the magic byte can be tested to detect overruns. */
+
+struct hdr
+ {
+ size_t size; /* Exact size requested by user. */
+ unsigned long int magic; /* Magic number to check header integrity. */
+ };
+
+/* Check the magicword and magicbyte, and if either is corrupted then
+ call the emergency abort function specified for the heap in use. */
+
+static void
+checkhdr (mdp, hdr)
+ struct mdesc *mdp;
+ CONST struct hdr *hdr;
+{
+ if (hdr -> magic != MAGICWORD ||
+ ((char *) &hdr[1])[hdr -> size] != MAGICBYTE)
+ {
+ (*mdp -> abortfunc)();
+ }
+}
+
+static void
+mfree_check (md, ptr)
+ PTR md;
+ PTR ptr;
+{
+ struct hdr *hdr = ((struct hdr *) ptr) - 1;
+ struct mdesc *mdp;
+
+ mdp = MD_TO_MDP (md);
+ checkhdr (mdp, hdr);
+ hdr -> magic = MAGICWORDFREE;
+ mdp -> mfree_hook = NULL;
+ mfree (md, (PTR)hdr);
+ mdp -> mfree_hook = mfree_check;
+}
+
+static PTR
+mmalloc_check (md, size)
+ PTR md;
+ size_t size;
+{
+ struct hdr *hdr;
+ struct mdesc *mdp;
+ size_t nbytes;
+
+ mdp = MD_TO_MDP (md);
+ mdp -> mmalloc_hook = NULL;
+ nbytes = sizeof (struct hdr) + size + 1;
+ hdr = (struct hdr *) mmalloc (md, nbytes);
+ mdp -> mmalloc_hook = mmalloc_check;
+ if (hdr != NULL)
+ {
+ hdr -> size = size;
+ hdr -> magic = MAGICWORD;
+ hdr++;
+ *((char *) hdr + size) = MAGICBYTE;
+ }
+ return ((PTR) hdr);
+}
+
+static PTR
+mrealloc_check (md, ptr, size)
+ PTR md;
+ PTR ptr;
+ size_t size;
+{
+ struct hdr *hdr = ((struct hdr *) ptr) - 1;
+ struct mdesc *mdp;
+ size_t nbytes;
+
+ mdp = MD_TO_MDP (md);
+ checkhdr (mdp, hdr);
+ mdp -> mfree_hook = NULL;
+ mdp -> mmalloc_hook = NULL;
+ mdp -> mrealloc_hook = NULL;
+ nbytes = sizeof (struct hdr) + size + 1;
+ hdr = (struct hdr *) mrealloc (md, (PTR) hdr, nbytes);
+ mdp -> mfree_hook = mfree_check;
+ mdp -> mmalloc_hook = mmalloc_check;
+ mdp -> mrealloc_hook = mrealloc_check;
+ if (hdr != NULL)
+ {
+ hdr -> size = size;
+ hdr++;
+ *((char *) hdr + size) = MAGICBYTE;
+ }
+ return ((PTR) hdr);
+}
+
+/* Turn on default checking for mmalloc/mrealloc/mfree, for the heap specified
+ by MD. If FUNC is non-NULL, it is a pointer to the function to call
+ to abort whenever memory corruption is detected. By default, this is the
+ standard library function abort().
+
+ Note that we disallow installation of initial checking hooks if mmalloc
+ has been called at any time for this particular heap, since if any region
+ that is allocated prior to installation of the hooks is subsequently
+ reallocated or freed after installation of the hooks, it is guaranteed
+ to trigger a memory corruption error. We do this by checking the state
+ of the MMALLOC_INITIALIZED flag.
+
+ However, we can call this function at any time after the initial call,
+ to update the function pointers to the checking routines and to the
+ user defined corruption handler routine, as long as these function pointers
+ have been previously extablished by the initial call. Note that we
+ do this automatically when remapping an previously used heap, to ensure
+ that the hooks get updated to the correct values, although the corruption
+ handler pointer gets set back to the default. The application can then
+ call mmcheck to use a different corruption handler if desired.
+
+ Returns non-zero if checking is successfully enabled, zero otherwise. */
+
+int
+mmcheck (md, func)
+ PTR md;
+ void (*func) PARAMS ((void));
+{
+ struct mdesc *mdp;
+ int rtnval;
+
+ mdp = MD_TO_MDP (md);
+
+ /* We can safely set or update the abort function at any time, regardless
+ of whether or not we successfully do anything else. */
+
+ mdp -> abortfunc = (func != NULL ? func : abort);
+
+ /* If we haven't yet called mmalloc the first time for this heap, or if we
+ have hooks that were previously installed, then allow the hooks to be
+ initialized or updated. */
+
+ if (1 /* FIXME: Always allow installation for now. */ ||
+ !(mdp -> flags & MMALLOC_INITIALIZED) ||
+ (mdp -> mfree_hook != NULL))
+ {
+ mdp -> mfree_hook = mfree_check;
+ mdp -> mmalloc_hook = mmalloc_check;
+ mdp -> mrealloc_hook = mrealloc_check;
+ mdp -> flags |= MMALLOC_MMCHECK_USED;
+ rtnval = 1;
+ }
+ else
+ {
+ rtnval = 0;
+ }
+
+ return (rtnval);
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/mmemalign.c b/gnu/usr.bin/gdb/mmalloc/mmemalign.c
new file mode 100644
index 000000000000..63350a215cd3
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mmemalign.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 1991, 1992 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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include "mmalloc.h"
+
+PTR
+mmemalign (md, alignment, size)
+ PTR md;
+ size_t alignment;
+ size_t size;
+{
+ PTR result;
+ unsigned long int adj;
+ struct alignlist *l;
+ struct mdesc *mdp;
+
+ size = ((size + alignment - 1) / alignment) * alignment;
+
+ if ((result = mmalloc (md, size)) != NULL)
+ {
+ adj = RESIDUAL (result, alignment);
+ if (adj != 0)
+ {
+ mdp = MD_TO_MDP (md);
+ for (l = mdp -> aligned_blocks; l != NULL; l = l -> next)
+ {
+ if (l -> aligned == NULL)
+ {
+ /* This slot is free. Use it. */
+ break;
+ }
+ }
+ if (l == NULL)
+ {
+ l = (struct alignlist *) mmalloc (md, sizeof (struct alignlist));
+ if (l == NULL)
+ {
+ mfree (md, result);
+ return (NULL);
+ }
+ }
+ l -> exact = result;
+ result = l -> aligned = (char *) result + alignment - adj;
+ l -> next = mdp -> aligned_blocks;
+ mdp -> aligned_blocks = l;
+ }
+ }
+ return (result);
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/mmstats.c b/gnu/usr.bin/gdb/mmalloc/mmstats.c
new file mode 100644
index 000000000000..d3846eb2dbe5
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mmstats.c
@@ -0,0 +1,46 @@
+/* Access the statistics maintained by `mmalloc'.
+ Copyright 1990, 1991, 1992 Free Software Foundation
+
+ Written May 1989 by Mike Haertel.
+ Modified Mar 1992 by Fred Fish. (fnf@cygnus.com)
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. 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 "mmalloc.h"
+
+/* FIXME: See the comment in mmalloc.h where struct mstats is defined.
+ None of the internal mmalloc structures should be externally visible
+ outside the library. */
+
+struct mstats
+mmstats (md)
+ PTR md;
+{
+ struct mstats result;
+ struct mdesc *mdp;
+
+ mdp = MD_TO_MDP (md);
+ result.bytes_total =
+ (char *) mdp -> morecore (mdp, 0) - mdp -> heapbase;
+ result.chunks_used = mdp -> heapstats.chunks_used;
+ result.bytes_used = mdp -> heapstats.bytes_used;
+ result.chunks_free = mdp -> heapstats.chunks_free;
+ result.bytes_free = mdp -> heapstats.bytes_free;
+ return (result);
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/mmtrace.c b/gnu/usr.bin/gdb/mmalloc/mmtrace.c
new file mode 100644
index 000000000000..73368a1b57aa
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mmtrace.c
@@ -0,0 +1,166 @@
+/* More debugging hooks for `mmalloc'.
+ Copyright 1991, 1992 Free Software Foundation
+
+ Written April 2, 1991 by John Gilmore of Cygnus Support
+ Based on mcheck.c by Mike Haertel.
+ Modified Mar 1992 by Fred Fish. (fnf@cygnus.com)
+
+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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include "mmalloc.h"
+
+#ifndef __GNU_LIBRARY__
+extern char *getenv ();
+#endif
+
+static FILE *mallstream;
+
+#if 0 /* FIXME: Disabled for now. */
+static char mallenv[] = "MALLOC_TRACE";
+static char mallbuf[BUFSIZ]; /* Buffer for the output. */
+#endif
+
+/* Address to breakpoint on accesses to... */
+static PTR mallwatch;
+
+/* Old hook values. */
+
+static void (*old_mfree_hook) PARAMS ((PTR, PTR));
+static PTR (*old_mmalloc_hook) PARAMS ((PTR, size_t));
+static PTR (*old_mrealloc_hook) PARAMS ((PTR, PTR, size_t));
+
+/* This function is called when the block being alloc'd, realloc'd, or
+ freed has an address matching the variable "mallwatch". In a debugger,
+ set "mallwatch" to the address of interest, then put a breakpoint on
+ tr_break. */
+
+static void
+tr_break ()
+{
+}
+
+static void
+tr_freehook (md, ptr)
+ PTR md;
+ PTR ptr;
+{
+ struct mdesc *mdp;
+
+ mdp = MD_TO_MDP (md);
+ /* Be sure to print it first. */
+ fprintf (mallstream, "- %08x\n", (unsigned int) ptr);
+ if (ptr == mallwatch)
+ tr_break ();
+ mdp -> mfree_hook = old_mfree_hook;
+ mfree (md, ptr);
+ mdp -> mfree_hook = tr_freehook;
+}
+
+static PTR
+tr_mallochook (md, size)
+ PTR md;
+ size_t size;
+{
+ PTR hdr;
+ struct mdesc *mdp;
+
+ mdp = MD_TO_MDP (md);
+ mdp -> mmalloc_hook = old_mmalloc_hook;
+ hdr = (PTR) mmalloc (md, size);
+ mdp -> mmalloc_hook = tr_mallochook;
+
+ /* We could be printing a NULL here; that's OK. */
+ fprintf (mallstream, "+ %08x %x\n", (unsigned int) hdr, size);
+
+ if (hdr == mallwatch)
+ tr_break ();
+
+ return (hdr);
+}
+
+static PTR
+tr_reallochook (md, ptr, size)
+ PTR md;
+ PTR ptr;
+ size_t size;
+{
+ PTR hdr;
+ struct mdesc *mdp;
+
+ mdp = MD_TO_MDP (md);
+
+ if (ptr == mallwatch)
+ tr_break ();
+
+ mdp -> mfree_hook = old_mfree_hook;
+ mdp -> mmalloc_hook = old_mmalloc_hook;
+ mdp -> mrealloc_hook = old_mrealloc_hook;
+ hdr = (PTR) mrealloc (md, ptr, size);
+ mdp -> mfree_hook = tr_freehook;
+ mdp -> mmalloc_hook = tr_mallochook;
+ mdp -> mrealloc_hook = tr_reallochook;
+ if (hdr == NULL)
+ /* Failed realloc. */
+ fprintf (mallstream, "! %08x %x\n", (unsigned int) ptr, size);
+ else
+ fprintf (mallstream, "< %08x\n> %08x %x\n", (unsigned int) ptr,
+ (unsigned int) hdr, size);
+
+ if (hdr == mallwatch)
+ tr_break ();
+
+ return hdr;
+}
+
+/* We enable tracing if either the environment variable MALLOC_TRACE
+ is set, or if the variable mallwatch has been patched to an address
+ that the debugging user wants us to stop on. When patching mallwatch,
+ don't forget to set a breakpoint on tr_break! */
+
+int
+mmtrace ()
+{
+#if 0 /* FIXME! This is disabled for now until we figure out how to
+ maintain a stack of hooks per heap, since we might have other
+ hooks (such as set by mmcheck) active also. */
+ char *mallfile;
+
+ mallfile = getenv (mallenv);
+ if (mallfile != NULL || mallwatch != NULL)
+ {
+ mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w");
+ if (mallstream != NULL)
+ {
+ /* Be sure it doesn't mmalloc its buffer! */
+ setbuf (mallstream, mallbuf);
+ fprintf (mallstream, "= Start\n");
+ old_mfree_hook = mdp -> mfree_hook;
+ mdp -> mfree_hook = tr_freehook;
+ old_mmalloc_hook = mdp -> mmalloc_hook;
+ mdp -> mmalloc_hook = tr_mallochook;
+ old_mrealloc_hook = mdp -> mrealloc_hook;
+ mdp -> mrealloc_hook = tr_reallochook;
+ }
+ }
+
+#endif /* 0 */
+
+ return (1);
+}
+
diff --git a/gnu/usr.bin/gdb/mmalloc/mrealloc.c b/gnu/usr.bin/gdb/mmalloc/mrealloc.c
new file mode 100644
index 000000000000..85bec565dadb
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mrealloc.c
@@ -0,0 +1,160 @@
+/* Change the size of a block allocated by `mmalloc'.
+ Copyright 1990, 1991 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. 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 <string.h> /* Prototypes for memcpy, memmove, memset, etc */
+
+#include "mmalloc.h"
+
+/* 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 mfree and mmalloc. */
+
+PTR
+mrealloc (md, ptr, size)
+ PTR md;
+ PTR ptr;
+ size_t size;
+{
+ struct mdesc *mdp;
+ PTR result;
+ int type;
+ size_t block, blocks, oldlimit;
+
+ if (size == 0)
+ {
+ mfree (md, ptr);
+ return (mmalloc (md, 0));
+ }
+ else if (ptr == NULL)
+ {
+ return (mmalloc (md, size));
+ }
+
+ mdp = MD_TO_MDP (md);
+
+ if (mdp -> mrealloc_hook != NULL)
+ {
+ return ((*mdp -> mrealloc_hook) (md, ptr, size));
+ }
+
+ block = BLOCK (ptr);
+
+ type = mdp -> heapinfo[block].busy.type;
+ switch (type)
+ {
+ case 0:
+ /* Maybe reallocate a large block to a small fragment. */
+ if (size <= BLOCKSIZE / 2)
+ {
+ result = mmalloc (md, size);
+ if (result != NULL)
+ {
+ memcpy (result, ptr, size);
+ mfree (md, 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 < mdp -> heapinfo[block].busy.info.size)
+ {
+ /* The new size is smaller; return excess memory to the free list. */
+ mdp -> heapinfo[block + blocks].busy.type = 0;
+ mdp -> heapinfo[block + blocks].busy.info.size
+ = mdp -> heapinfo[block].busy.info.size - blocks;
+ mdp -> heapinfo[block].busy.info.size = blocks;
+ mfree (md, ADDRESS (block + blocks));
+ result = ptr;
+ }
+ else if (blocks == mdp -> 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 = mdp -> heapinfo[block].busy.info.size;
+ /* Prevent free from actually returning memory to the system. */
+ oldlimit = mdp -> heaplimit;
+ mdp -> heaplimit = 0;
+ mfree (md, ptr);
+ mdp -> heaplimit = oldlimit;
+ result = mmalloc (md, size);
+ if (result == NULL)
+ {
+ mmalloc (md, 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 > (size_t) (1 << (type - 1)) && size <= (size_t) (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 = mmalloc (md, size);
+ if (result == NULL)
+ {
+ return (NULL);
+ }
+ memcpy (result, ptr, MIN (size, (size_t) 1 << type));
+ mfree (md, ptr);
+ }
+ break;
+ }
+
+ return (result);
+}
+
+/* When using this package, provide a version of malloc/realloc/free built
+ on top of it, so that if we use the default sbrk() region we will not
+ collide with another malloc package trying to do the same thing, if
+ the application contains any "hidden" calls to malloc/realloc/free (such
+ as inside a system library). */
+
+PTR
+realloc (ptr, size)
+ PTR ptr;
+ size_t size;
+{
+ return (mrealloc ((PTR) NULL, ptr, size));
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/mvalloc.c b/gnu/usr.bin/gdb/mmalloc/mvalloc.c
new file mode 100644
index 000000000000..1ffba7865cf7
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/mvalloc.c
@@ -0,0 +1,40 @@
+/* Allocate memory on a page boundary.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include "mmalloc.h"
+
+/* Cache the pagesize for the current host machine. Note that if the host
+ does not readily provide a getpagesize() function, we need to emulate it
+ elsewhere, not clutter up this file with lots of kluges to try to figure
+ it out. */
+
+static size_t pagesize;
+extern int getpagesize PARAMS ((void));
+
+PTR
+mvalloc (md, size)
+ PTR md;
+ size_t size;
+{
+ if (pagesize == 0)
+ {
+ pagesize = getpagesize ();
+ }
+
+ return (mmemalign (md, pagesize, size));
+}
diff --git a/gnu/usr.bin/gdb/mmalloc/sbrk-sup.c b/gnu/usr.bin/gdb/mmalloc/sbrk-sup.c
new file mode 100644
index 000000000000..e6a57d6ccad2
--- /dev/null
+++ b/gnu/usr.bin/gdb/mmalloc/sbrk-sup.c
@@ -0,0 +1,96 @@
+/* Support for sbrk() regions.
+ Copyright 1992 Free Software Foundation, Inc.
+ Contributed by Fred Fish at Cygnus Support. fnf@cygnus.com
+
+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 Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <string.h> /* Prototypes for memcpy, memmove, memset, etc */
+
+#include "mmalloc.h"
+
+extern PTR sbrk ();
+
+/* The mmalloc() package can use a single implicit malloc descriptor
+ for mmalloc/mrealloc/mfree operations which do not supply an explicit
+ descriptor. For these operations, sbrk() is used to obtain more core
+ from the system, or return core. This allows mmalloc() to provide
+ backwards compatibility with the non-mmap'd version. */
+
+struct mdesc *__mmalloc_default_mdp;
+
+/* Use sbrk() to get more core. */
+
+static PTR
+sbrk_morecore (mdp, size)
+ struct mdesc *mdp;
+ int size;
+{
+ PTR result;
+
+ if ((result = sbrk (size)) == (PTR) -1)
+ {
+ result = NULL;
+ }
+ else
+ {
+ mdp -> breakval += size;
+ mdp -> top += size;
+ }
+ return (result);
+}
+
+/* Initialize the default malloc descriptor if this is the first time
+ a request has been made to use the default sbrk'd region.
+
+ Since no alignment guarantees are made about the initial value returned
+ by sbrk, test the initial value and (if necessary) sbrk enough additional
+ memory to start off with alignment to BLOCKSIZE. We actually only need
+ it aligned to an alignment suitable for any object, so this is overkill.
+ But at most it wastes just part of one BLOCKSIZE chunk of memory and
+ minimizes portability problems by avoiding us having to figure out
+ what the actual minimal alignment is. The rest of the malloc code
+ avoids this as well, by always aligning to the minimum of the requested
+ size rounded up to a power of two, or to BLOCKSIZE.
+
+ Note that we are going to use some memory starting at this initial sbrk
+ address for the sbrk region malloc descriptor, which is a struct, so the
+ base address must be suitably aligned. */
+
+struct mdesc *
+__mmalloc_sbrk_init ()
+{
+ PTR base;
+ unsigned int adj;
+
+ base = sbrk (0);
+ adj = RESIDUAL (base, BLOCKSIZE);
+ if (adj != 0)
+ {
+ sbrk (BLOCKSIZE - adj);
+ base = sbrk (0);
+ }
+ __mmalloc_default_mdp = (struct mdesc *) sbrk (sizeof (struct mdesc));
+ memset ((char *) __mmalloc_default_mdp, 0, sizeof (struct mdesc));
+ __mmalloc_default_mdp -> morecore = sbrk_morecore;
+ __mmalloc_default_mdp -> base = base;
+ __mmalloc_default_mdp -> breakval = __mmalloc_default_mdp -> top = sbrk (0);
+ __mmalloc_default_mdp -> fd = -1;
+ return (__mmalloc_default_mdp);
+}
+
+
diff --git a/gnu/usr.bin/gdb/ngdb.i386/Makefile b/gnu/usr.bin/gdb/ngdb.i386/Makefile
deleted file mode 100644
index 3bf4c6c94929..000000000000
--- a/gnu/usr.bin/gdb/ngdb.i386/Makefile
+++ /dev/null
@@ -1,27 +0,0 @@
-# %W% (Berkeley) %G%
-
-.include "../config/Makefile.$(MACHINE)"
-
-PROG= ngdb
-SRCS= i386bsd-dep.c blockframe.c
-GDBOBJS+= i386-pinsn.o \
- breakpoint.o command.o copying.o core.o \
- cplus-dem.o dbxread.o environ.o eval.o expprint.o \
- expread.o findvar.o infcmd.o inflow.o infrun.o \
- main.o obstack.o printcmd.o regex.o remote.o \
- remote-sl.o source.o stack.o symmisc.o symtab.o \
- utils.o valarith.o valops.o valprint.o values.o \
- version.o \
- funmap.o history.o keymaps.o readline.o \
- init.o
-CFLAGS+= -g -I$(.CURDIR) -I.. -I$(.CURDIR)/.. -I$(.CURDIR)/../config \
- -I/usr/src/sys.newvm \
- -DNEWVM -DHAVE_VPRINTF -DVI_MODE -DKERNELDEBUG
-# CC= /usr/old/bin/cc
-# CC= cc -traditional
-LDADD+= $(GDBOBJS:S/^/..\//g) -ltermcap
-NOMAN= noman
-
-.PATH: $(.CURDIR)/../config $(.CURDIR)/..
-
-.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/gdb/obstack.c b/gnu/usr.bin/gdb/obstack.c
deleted file mode 100644
index 6f4b282d1e7a..000000000000
--- a/gnu/usr.bin/gdb/obstack.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/* 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.
-
-
-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! */
-
-
-#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;
-
-/* 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.
- Pick a number small enough that when rounded up to DEFAULT_ROUNDING
- it is still smaller than 4096 - 4. */
- {
- int extra = 4;
- if (extra < DEFAULT_ROUNDING)
- extra = DEFAULT_ROUNDING;
- size = 4096 - extra;
- }
-
- h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
- h->freefun = freefun;
- h->chunk_size = size;
- h->alignment_mask = alignment - 1;
-
- chunk = h->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. */
-
-void
-_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;
-
- /* Compute size for new chunk. */
- new_size = (obj_size + length) << 1;
- if (new_size < h->chunk_size)
- new_size = h->chunk_size;
-
- /* Allocate and initialize the new chunk. */
- new_chunk = h->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 because these
- structures are aligned at least that much. */
- for (i = (obj_size + sizeof (COPYING_UNIT) - 1) / sizeof (COPYING_UNIT) - 1;
- i >= 0; i--)
- ((COPYING_UNIT *)new_chunk->contents)[i]
- = ((COPYING_UNIT *)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. */
-
-void
-#ifdef __STDC__
-#undef obstack_free
-obstack_free (struct obstack *h, POINTER obj)
-#else
-_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;
- while (lp != 0 && ((POINTER)lp > obj || (POINTER)(lp)->limit < obj))
- {
- plp = lp -> prev;
- (*h->freefun) (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__
-void
-_obstack_free (h, obj)
- struct obstack *h;
- POINTER obj;
-{
- obstack_free (h, obj);
-}
-#endif
-
-#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/gnu/usr.bin/gdb/readline/ChangeLog b/gnu/usr.bin/gdb/readline/ChangeLog
deleted file mode 100644
index b72a59daed03..000000000000
--- a/gnu/usr.bin/gdb/readline/ChangeLog
+++ /dev/null
@@ -1,98 +0,0 @@
-Thu Feb 8 01:04:00 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
-
- * Makefile (the *other* libreadline.a): Uncomment out ranlib line.
-
-Thu Feb 1 17:50:22 1990 Jim Kingdon (kingdon at pogo.ai.mit.edu)
-
- * Makefile (libreadline.a): Uncomment out ranlib line.
-
-Sun Nov 26 16:29:11 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
-
- * readline.c (rl_deprep_terminal): Only restore local_mode_flags
- if they had been set.
-
-Thu Oct 19 17:18:40 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
-
- * Move vi_doing_insert from vi_mode.c to readline.c
-
- * readline.c: Move compare_strings before its use.
- Remove declarations.
-
- * readline.c: Move defining_kbd_macro above rl_dispatch.
- (rl_dispatch): Remove "extern int defining_kbd_macro".
-
-Mon Oct 16 11:56:03 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
-
- * readline.c (rl_set_signals): Remove unnecessary "static int
- rl_signal_handler()".
-
-Sat Sep 30 14:51:56 1989 Jim Kingdon (kingdon at hobbes.ai.mit.edu)
-
- * readline.c (rl_initialize): Change parsing_conditionalized_out
- to static.
- (rl_dispatch): Change defining_kbd_macro to static.
- (rl_newline): Change vi_doing_insert to static.
-
-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/gnu/usr.bin/gdb/readline/Makefile.gnu b/gnu/usr.bin/gdb/readline/Makefile.gnu
deleted file mode 100644
index dc1153984e86..000000000000
--- a/gnu/usr.bin/gdb/readline/Makefile.gnu
+++ /dev/null
@@ -1,114 +0,0 @@
-## -*- 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) $*.c
-
-# 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/gnu/lib
-INCDIR = /usr/gnu/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 this out if you don't think that anyone will ever desire
-# the vi line editing mode and features.
-READLINE_DEFINES = -DVI_MODE
-
-DEBUG_FLAGS = -g
-LDFLAGS = $(DEBUG_FLAGS)
-CFLAGS = $(DEBUG_FLAGS) $(TYPE) $(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 keymaps.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
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) $*.c
-
-history.o: history.c history.h
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) $*.c
-
-funmap.o: readline.h
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) $*.c
-
-keymaps.o: emacs_keymap.c vi_keymap.c keymaps.h chardefs.h keymaps.c
- $(CC) -c $(CFLAGS) $(CPPFLAGS) $(READLINE_DEFINES) \
- $(LOCAL_INCLUDES) $*.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/gnu/usr.bin/gdb/readline/chardefs.h b/gnu/usr.bin/gdb/readline/chardefs.h
deleted file mode 100644
index 9749ae489f46..000000000000
--- a/gnu/usr.bin/gdb/readline/chardefs.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* 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/gnu/usr.bin/gdb/readline/emacs_keymap.c b/gnu/usr.bin/gdb/readline/emacs_keymap.c
deleted file mode 100644
index 7030e69f6b7c..000000000000
--- a/gnu/usr.bin/gdb/readline/emacs_keymap.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/* 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 FILE
-#include <stdio.h>
-#endif /* FILE */
-
-#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, rl_re_read_init_file }, /* 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/gnu/usr.bin/gdb/readline/funmap.c b/gnu/usr.bin/gdb/readline/funmap.c
deleted file mode 100644
index 357e716f2003..000000000000
--- a/gnu/usr.bin/gdb/readline/funmap.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/* 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 just_testing_ar_tmp = 0;
-static int just_testing_ar_tmp_2 = 5;
-int foo_testing_ar;
-
-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
-
-/* **************************************************************** */
-/* */
-/* xmalloc and xrealloc () */
-/* */
-/* **************************************************************** */
-
-static char *
-xmalloc (bytes)
- int bytes;
-{
- static memory_error_and_abort ();
- char *temp = (char *)malloc (bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static char *
-xrealloc (pointer, bytes)
- char *pointer;
- int bytes;
-{
- static memory_error_and_abort ();
- char *temp = (char *)realloc (pointer, bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static
-memory_error_and_abort ()
-{
- fprintf (stderr, "history: Out of virtual memory!\n");
- abort ();
-}
-#endif /* STATIC_MALLOC */
diff --git a/gnu/usr.bin/gdb/readline/history.c b/gnu/usr.bin/gdb/readline/history.c
deleted file mode 100644
index 7087718edc30..000000000000
--- a/gnu/usr.bin/gdb/readline/history.c
+++ /dev/null
@@ -1,1462 +0,0 @@
-/* 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);
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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[2];
- 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);
- }
- 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] == '*')
- {
- *caller_index = i + 1;
- return (history_arg_extract (1, '$', from));
- }
-
- /* `$' 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. */
-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 == '$')
- 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
-
-/* **************************************************************** */
-/* */
-/* xmalloc and xrealloc () */
-/* */
-/* **************************************************************** */
-
-static char *
-xmalloc (bytes)
- int bytes;
-{
- static memory_error_and_abort ();
- char *temp = (char *)malloc (bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static char *
-xrealloc (pointer, bytes)
- char *pointer;
- int bytes;
-{
- static memory_error_and_abort ();
- char *temp = (char *)realloc (pointer, bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static
-memory_error_and_abort ()
-{
- fprintf (stderr, "history: Out of virtual memory!\n");
- abort ();
-}
-#endif /* STATIC_MALLOC */
-
-
-/* **************************************************************** */
-/* */
-/* 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 */
-
-/*
-* Local variables:
-* compile-command: "gcc -g -DTEST -o history history.c"
-* end:
-*/
diff --git a/gnu/usr.bin/gdb/readline/history.h b/gnu/usr.bin/gdb/readline/history.h
deleted file mode 100644
index 0bac2092079e..000000000000
--- a/gnu/usr.bin/gdb/readline/history.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* 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/gnu/usr.bin/gdb/readline/keymaps.c b/gnu/usr.bin/gdb/readline/keymaps.c
deleted file mode 100644
index e0c5e394a421..000000000000
--- a/gnu/usr.bin/gdb/readline/keymaps.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* 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
-
-/* **************************************************************** */
-/* */
-/* xmalloc and xrealloc () */
-/* */
-/* **************************************************************** */
-
-static char *
-xmalloc (bytes)
- int bytes;
-{
- static memory_error_and_abort ();
- char *temp = (char *)malloc (bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static char *
-xrealloc (pointer, bytes)
- char *pointer;
- int bytes;
-{
- static memory_error_and_abort ();
- char *temp = (char *)realloc (pointer, bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static
-memory_error_and_abort ()
-{
- fprintf (stderr, "readline: Out of virtual memory!\n");
- abort ();
-}
-#endif /* STATIC_MALLOC */
diff --git a/gnu/usr.bin/gdb/readline/keymaps.h b/gnu/usr.bin/gdb/readline/keymaps.h
deleted file mode 100644
index 3c577b398f59..000000000000
--- a/gnu/usr.bin/gdb/readline/keymaps.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* 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/gnu/usr.bin/gdb/readline/readline.c b/gnu/usr.bin/gdb/readline/readline.c
deleted file mode 100644
index 3e8f9a38a1d8..000000000000
--- a/gnu/usr.bin/gdb/readline/readline.c
+++ /dev/null
@@ -1,5557 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)readline.c 6.4 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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>
-#include <string.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)
-#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 */
-#ifdef hpux
-#include <ndir.h>
-#else
-#include <dirent.h>
-#define direct dirent
-#define d_namlen d_reclen
-#endif /* hpux */
-#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 start_insert ();
-static end_insert ();
-
-/* This typedef is equivalant to the one for Function; it allows us
- to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
-typedef void SigHandler ();
-
-#ifdef SIGWINCH
-static void rl_handle_sigwinch ();
-static SigHandler *old_sigwinch = (SigHandler *)NULL;
-#endif
-
-/* If on, then readline handles signals in a way that doesn't screw. */
-/* #define HANDLE_SIGNALS */
-
-#if defined (SYSV)
-#ifdef HANDLE_SIGNALS
-#undef HANDLE_SIGNALS
-#endif
-#endif
-
-/* Stupid comparison routine for qsort () ing strings. */
-static int
-compare_strings (s1, s2)
- char **s1, **s2;
-{
- return (strcmp (*s1, *s2));
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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;
-
-/* 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
-
-
-/* **************************************************************** */
-/* */
-/* 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 SIGWINCH
- old_sigwinch = (SigHandler *)signal (SIGWINCH, rl_handle_sigwinch);
-#endif
-
-#ifdef HANDLE_SIGNALS
- rl_set_signals ();
-#endif
-
- value = readline_internal ();
- rl_deprep_terminal ();
-
-#ifdef SIGWINCH
- signal (SIGWINCH, old_sigwinch);
-#endif
-
-#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));
-}
-
-
-/* Variables for 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;
-
-/* Non-zero means to save keys that we dispatch on in a kbd macro. */
-static int defining_kbd_macro = 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;
-
-
-/* **************************************************************** */
-/* */
-/* Signal Handling */
-/* */
-/* **************************************************************** */
-
-#ifdef SIGWINCH
-static void
-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 void
-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 SIGWINCH
- signal (SIGWINCH, old_sigwinch);
-#endif
-
-#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);
-#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
-}
-#endif /* HANDLE_SIGNALS */
-
-
-
-/* **************************************************************** */
-/* */
-/* 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.
- Result is KEY if there was a key, or -2 if there wasn't. */
-int
-rl_get_char ()
-{
- int key;
-
- if (push_index == pop_index)
- return (-2);
-
- key = ibuffer[pop_index++];
-
- if (pop_index >= ibuffer_len)
- pop_index = 0;
-
- return (key);
-}
-
-/* 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);
-}
-
-
-
-static void
-rl_getc (stream)
- FILE *stream;
-{
- int result;
- int nchar;
- int tty = fileno(stream);
- char buf[512]; /* XXX - must be at least as large as ibuffer */
-
- while (1)
- {
- if (ioctl(tty, FIONREAD, &nchar) == -1)
- nchar = sizeof(buf);
- else if (nchar <= 0)
- nchar = 1;
- result = ibuffer_space();
- if (nchar > result)
- nchar = result;
- result = read(tty, buf, nchar);
- if (result > 0)
- {
- register char *cp = buf;
-
- while (--result >= 0)
- rl_stuff_char(*cp++);
- return;
- }
- if (errno != EINTR)
- {
- rl_stuff_char(EOF);
- return;
- }
- }
-}
-
-/* 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);
-
- while ((c = rl_get_char()) == -2)
- {
- if (rl_event_hook)
- {
- (*rl_event_hook) ();
- if ((c = rl_get_char()) != -2)
- return (c);
- }
- rl_getc(in_stream);
- }
- }
-#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 */
- return (c);
-}
-
-/* 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)
- {
- static add_macro_char ();
-
- 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;
-}
-
-
-/* **************************************************************** */
-/* */
-/* Hacking Keyboard Macros */
-/* */
-/* **************************************************************** */
-
-/* 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;
-{
- static push_executing_macro ();
-
- 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])
- {
- static pop_executing_macro ();
-
- 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
-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
-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
-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));
-}
-
-
-/* Non-zero means do not parse any lines other than comments and
- parser directives. */
-static unsigned char parsing_conditionalized_out = 0;
-
-/* **************************************************************** */
-/* */
-/* 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 TIOCGETP
- 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 */
-#endif /* TIOCGETP */
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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;
- }
- }
- }
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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. */
-int horizontal_scroll_mode = 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 ();
-
-/* 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 (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 || !*term_IC))
- {
- output_some_chars (nfd, (ne - nfd));
- last_c_pos += (ne - nfd);
- }
- else
- {
- if (*ols)
- {
- start_insert (lendiff);
- output_some_chars (nfd, lendiff);
- last_c_pos += lendiff;
- end_insert ();
- }
- 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;
- static void output_character_function ();
-
- /* 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 ();
-}
-
-/* **************************************************************** */
-/* */
-/* 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);
- term_ip = tgetstr ("ip", &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." */
-#ifdef notdef
- /* XXX Circumvent broken code. */
- terminal_can_insert = (term_IC || term_im || term_ic || term_ip);
-#endif
-
- 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);
- }
-}
-
-/* Prepare to insert by inserting COUNT blank spaces. */
-static
-start_insert (count)
- int count;
-{
- if (term_im && *term_im)
- tputs (term_im, 1, output_character_function);
-
- if (term_IC && *term_IC &&
- (count > 1 || !term_ic || !*term_ic))
- {
- char *tgoto (), *buffer;
- buffer = tgoto (term_IC, 0, count);
- tputs (buffer, 1, output_character_function);
- }
- else
- {
- if (term_ic && *term_ic)
- while (count--)
- tputs (term_ic, 1, output_character_function);
- }
-}
-
-/* We are finished doing our insertion. Send ending string. */
-static
-end_insert ()
-{
- 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);
- }
-}
-
-
-/* **************************************************************** */
-/* */
-/* Saving and Restoring the TTY */
-/* */
-/* **************************************************************** */
-
-#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);
-
- /* 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 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 | EVENP)) == (ODDP | EVENP))
- {
-#ifdef PASS8
- the_ttybuff.sg_flags |= PASS8;
-#endif
-
-#if defined (TIOCLGET) && defined (LPASS8)
- {
- int flags;
- ioctl (tty, TIOCLGET, &flags);
- local_mode_flags = flags;
- 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);
-}
-
-/* Restore the terminal to its original state. */
-static
-rl_deprep_terminal ()
-{
- int tty = fileno (rl_instream);
-
-#if defined (TIOCLGET) && defined (LPASS8)
- if ((the_ttybuff.sg_flags & (ODDP | EVENP)) == (ODDP | EVENP))
- ioctl (tty, TIOCLSET, &local_mode_flags);
-#endif
-
-#ifdef TIOCSLTC
- ioctl (tty, TIOCSLTC, &original_ltchars);
-#endif
-
-#ifdef TIOCSETC
- ioctl (tty, TIOCSETC, &original_tchars);
-#endif
-
- the_ttybuff.sg_flags = original_tty_flags;
- ioctl (tty, TIOCSETN, &the_ttybuff);
- readline_echoing_p = 1;
-}
-
-#else /* !defined (NEW_TTY_DRIVER) */
-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|ISTRIP|INPCK);
-
-#ifndef HANDLE_SIGNALS
- tio.c_lflag &= ~ISIG;
-#endif
-
- tio.c_cc[VEOF] = 1; /* really: MIN */
- tio.c_cc[VEOL] = 0; /* really: TIME */
- ioctl (tty, TCSETAW,&tio);
-}
-
-static
-rl_deprep_terminal ()
-{
- int tty = fileno (rl_instream);
- ioctl (tty, TCSETAW, &otio);
-}
-#endif /* NEW_TTY_DRIVER */
-
-
-/* **************************************************************** */
-/* */
-/* 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;
-{
- 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. */
-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);
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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';
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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.
-*/
-
-
-/* **************************************************************** */
-/* */
-/* 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;
-
- move_vert(curr_line);
- move_cursor_relative (0, the_line); /* XXX is this right */
- 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;
- static void output_character_function ();
-
- 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;
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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 descreaser;
-
- string = (char *)alloca (1024 + 1);
-
- for (i = 0; i < 1024; i++)
- string[i] = c;
-
- while (count)
- {
- descreaser = (count > 1024 ? 1024 : count);
- string[descreaser] = '\0';
- rl_insert_text (string);
- count -= descreaser;
- }
- 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 slen, key = 0, t;
-
- i = 0;
- string = (char *)alloca (ibuffer_len + 1);
- string[i++] = c;
-
- while ((key = rl_get_char()) != -2 &&
- (keymap[key].type == ISFUNC &&
- keymap[key].function == rl_insert))
- string[i++] = key;
-
- if (key != -2)
- 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 (in_stream);
- rl_insert (count, c);
-}
-
-/* Insert a tab character. */
-rl_tab_insert (count)
- int count;
-{
- rl_insert (count, '\t');
-}
-
-#ifdef VI_MODE
-/* Non-zero means enter insertion mode. */
-static vi_doing_insert = 0;
-#endif
-
-/* 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
- {
- 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--;
- 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;
-{
- if (count < 0)
- {
- rl_rubout (-count);
- return;
- }
-
- if (rl_point == rl_end)
- {
- ding ();
- return;
- }
-
-#ifdef VI_MODE
- if ((count > 1) || ((count == 1) && (rl_editing_mode == vi_mode)))
-#else
- if (count > 1)
-#endif
- {
- int orig_point = rl_point;
- while (count && (rl_point < rl_end))
- {
- rl_point++;
- count--;
- }
- rl_kill_text (orig_point, rl_point);
- rl_point = orig_point;
- }
- else
- rl_delete_text (rl_point, rl_point + 1);
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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;
- }
-}
-
-
-
-/* **************************************************************** */
-/* */
-/* 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--;
- }
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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);
- if (running_in_emacs)
- printf ("%s", the_line);
-}
-
-/* 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 (in_stream);
- 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:
- 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 *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 *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 *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);
- }
-}
-
-/* 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);
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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;
- }
- }
-}
-
-/* **************************************************************** */
-/* */
-/* 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;
- }
-}
-
-
-
-/* **************************************************************** */
-/* */
-/* 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;
-{
-}
-
-
-
-/* **************************************************************** */
-/* */
-/* 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 (in_stream);
-
- /* 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;
-}
-
-/* **************************************************************** */
-/* */
-/* 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;
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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 *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;
-#ifdef SHELL
- {
- extern int follow_symbolic_links;
- char *make_absolute ();
-
- if (follow_symbolic_links && (strcmp (dirname, ".") != 0))
- {
- temp_dirname = make_absolute (dirname, get_working_directory (""));
-
- if (temp_dirname)
- {
- free (dirname);
- dirname = temp_dirname;
- }
- }
- }
-#endif /* SHELL */
- }
- 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);
- }
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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;
- int start;
-
- /* 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;
-
- /* Handle mapping of the ESC Key in vi mode */
- start = 0;
-#ifdef VI_MODE
- if ((rl_editing_mode == vi_mode) && (keys[0] == ESC))
- {
- start++;
- map = vi_movement_keymap;
- if(keys[1] == ESC)
- {
- extern KEYMAP_ENTRY_ARRAY vi_escape_keymap;
-
- start++;
- map = vi_escape_keymap;
- }
- }
-#endif
-
- /* Bind keys, making new keymaps as necessary. */
- for (i = start; 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;
- }
-
- array[l] = '\0';
- *len = l;
- 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;
- static int stricmp ();
-
- 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;
-{
- 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 = getc(file)) != EOF)
- {
- /* If comment, flush to EOL. */
- if (c == '#')
- {
- while ((c = 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 = 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;
- static int stricmp ();
-
- /* 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;
- static int stricmp ();
-
- /* 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 *funname, *kname;
- static int substring_member_of_array (), stricmp ();
- 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;
-{
- static int strnicmp (), stricmp ();
-
- 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;
- }
-}
-
-/* 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;
- static int stricmp ();
-
- 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);
-}
-
-
-/* **************************************************************** */
-/* */
-/* 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);
-}
-
-
-#ifdef STATIC_MALLOC
-
-/* **************************************************************** */
-/* */
-/* xmalloc and xrealloc () */
-/* */
-/* **************************************************************** */
-
-static char *
-xmalloc (bytes)
- int bytes;
-{
- static memory_error_and_abort ();
- char *temp = (char *)malloc (bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static char *
-xrealloc (pointer, bytes)
- char *pointer;
- int bytes;
-{
- static memory_error_and_abort ();
- char *temp = (char *)realloc (pointer, bytes);
-
- if (!temp)
- memory_error_and_abort ();
- return (temp);
-}
-
-static
-memory_error_and_abort ()
-{
- fprintf (stderr, "readline: Out of virtual memory!\n");
- abort ();
-}
-#endif /* STATIC_MALLOC */
-
-
-/* **************************************************************** */
-/* */
-/* 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 */
-
-
-/*
- * 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/gnu/usr.bin/gdb/readline/readline.h b/gnu/usr.bin/gdb/readline/readline.h
deleted file mode 100644
index 7d7fbe7c3c79..000000000000
--- a/gnu/usr.bin/gdb/readline/readline.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/* 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;
-
-/* **************************************************************** */
-/* */
-/* 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/gnu/usr.bin/gdb/readline/vi_keymap.c b/gnu/usr.bin/gdb/readline/vi_keymap.c
deleted file mode 100644
index 71c7ec8506cc..000000000000
--- a/gnu/usr.bin/gdb/readline/vi_keymap.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * @(#)vi_keymap.c 6.4 (Berkeley) 5/8/91
- */
-
-/* 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_previous_history}, /* + */
- { ISFUNC, rl_vi_char_search }, /* , */
- { ISFUNC, rl_get_next_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/gnu/usr.bin/gdb/readline/vi_mode.c b/gnu/usr.bin/gdb/readline/vi_mode.c
deleted file mode 100644
index 3a13cc6c862a..000000000000
--- a/gnu/usr.bin/gdb/readline/vi_mode.c
+++ /dev/null
@@ -1,875 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * @(#)vi_mode.c 6.4 (Berkeley) 5/8/91
- */
-
-/* vi_mode.c -- A vi emulation mode for Bash.
- Mostly written by Jeff Sparkes (jeff1@????).
- */
-
-
-/* **************************************************************** */
-/* */
-/* VI Emulation Mode */
-/* */
-/* **************************************************************** */
-
-/* Last string searched for from `/' or `?'. */
-static char *vi_last_search = (char *)NULL;
-static int vi_histpos;
-
-/* *** 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);
-}
-
-/* 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;
- char *p;
-
- switch (key)
- {
- case '?':
- dir = 1;
- break;
-
- case '/':
- dir = -1;
- break;
-
- default:
- ding ();
- return;
- }
-
- vi_histpos = where_history ();
- maybe_save_line ();
-
- /* 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);
-
- while (c = rl_read_key (in_stream))
- {
- switch (c)
- {
- case CTRL('W'):
- case CTRL('U'):
- case CTRL('H'):
- case RUBOUT:
- 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]))
- {
- rl_vi_end_word (1, 'E');
- rl_point++;
- }
- rl_complete_internal ('*');
- 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;
- 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);
- 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))
- {
- if(rl_point != rl_end)
- rl_point++;
- }
-
- 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 ()
-{
- int c, save;
-
- rl_mark = rl_point;
- c = rl_read_key (in_stream);
-
- if (!member (c, vi_motion))
- {
- if (digit (c))
- {
- save = rl_numeric_arg;
- rl_digit_loop1 ();
- rl_numeric_arg *= save;
- }
- 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--;
- while((rl_point > 0) && whitespace (the_line[rl_point]))
- rl_point--;
- 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);
- 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;
-{
- if (uppercase_p (key))
- rl_stuff_char ('$');
-
- if (rl_vi_domove ())
- {
- ding ();
- return;
- }
-
- rl_kill_text (rl_point, rl_mark);
-}
-
-rl_vi_change_to (count, key)
- int count, key;
-{
- if (uppercase_p (key))
- rl_stuff_char ('$');
-
- if (rl_vi_domove ())
- {
- ding ();
- return;
- }
-
- 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 save = rl_point;
-
- if (uppercase_p (key))
- rl_stuff_char ('$');
-
- if (rl_vi_domove ())
- {
- 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);
- if (rl_point > 0)
- rl_backward (1);
- }
- else
- rl_delete (count);
-}
-
-/* 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_read_key();
-
- 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_read_key();
-
- switch (c)
- {
- case '\033':
- case CTRL('C'):
- return;
-
- default:
- rl_begin_undo_group ();
- rl_delete (1);
- 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);
-
- 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);
- 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[CTRL('H')].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;
-}
diff --git a/gnu/usr.bin/gdb/remote-sl.c b/gnu/usr.bin/gdb/remote-sl.c
deleted file mode 100644
index 4c72197f1ae1..000000000000
--- a/gnu/usr.bin/gdb/remote-sl.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * The binary remote protocol is still under development at LBL;
- * the current version can't be released.
- * Sorry, folks...
- */
-int
-sl_open()
-{
- return -1;
-}
diff --git a/gnu/usr.bin/gdb/remote.c b/gnu/usr.bin/gdb/remote.c
deleted file mode 100644
index 8b65522d804d..000000000000
--- a/gnu/usr.bin/gdb/remote.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*-
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $Header: /home/cvs/386BSD/src/gnu/usr.bin/gdb/remote.c,v 1.1 1993/06/29 09:47:34 nate Exp $;
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)remote.c 6.5 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-#include "param.h"
-
-#include <stdio.h>
-#include <varargs.h>
-
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/file.h>
-
-#include "defs.h"
-#include "frame.h"
-#include "inferior.h"
-#include "wait.h"
-
-#include "kgdb_proto.h"
-
-static FILE *kiodebug;
-static int icache = 1;
-extern int kernel_debugging;
-
-static int remote_cache_valid;
-static int remote_instub;
-
-static void remote_signal();
-static void remote_debug();
-static void print_msg();
-
-static int remote_mtu;
-static int (*send_msg)();
-static int (*recv_msg)();
-static void (*closelink)();
-
-static u_char *inbuffer;
-static u_char *outbuffer;
-
-/*
- * Statistics.
- */
-static int remote_ierrs;
-static int remote_oerrs;
-static int remote_seqerrs;
-static int remote_spurious;
-
-#define PUTCMD(cmd) m_xchg(cmd, (u_char *)0, 0, (u_char *)0, (int *)0)
-
-/*
- * Send an outbound message to the remote machine and read the reply.
- * Either or both message buffers may be NULL.
- */
-static int
-m_xchg(type, out, outlen, in, inlen)
- int type;
- u_char *out;
- int outlen;
- u_char *in;
- int *inlen;
-{
- register int err, (*send)() = send_msg, (*recv)() = recv_msg;
- int ack;
- static int seqbit = 0;
-
- if (!remote_instub) {
- remote_instub = 1;
- PUTCMD(KGDB_EXEC);
- }
-
- seqbit ^= KGDB_SEQ;
- while (1) {
- err = (*send)(type | seqbit, out, outlen);
- if (err) {
- ++remote_oerrs;
- if (kiodebug)
- remote_debug("send error %d\n", err);
- }
- if (kiodebug)
- print_msg(type | seqbit, out, outlen, 'O');
-
- recv:
- err = (*recv)(&ack, in, inlen);
- if (err) {
- ++remote_ierrs;
- if (kiodebug)
- remote_debug("recv error %d\n", err);
- remote_cache_valid = 0;
- } else if (kiodebug)
- print_msg(ack, in, inlen ? *inlen : 0, 'I');
-
- if (err)
- continue;
-
- if ((ack & KGDB_ACK) == 0 || KGDB_CMD(ack) != KGDB_CMD(type)) {
- ++remote_spurious;
- continue;
- }
- if ((ack & KGDB_SEQ) ^ seqbit) {
- ++remote_seqerrs;
- goto recv;
- }
- return ack;
- }
-}
-
-/*
- * Wait for the specified message type. Discard anything else.
- * (this is used by 'remote-signal' to help us resync with other side.)
- */
-static void
-m_recv(type, in, inlen)
- int type;
- u_char *in;
- int *inlen;
-{
- int reply, err;
-
- while (1) {
- err = (*recv_msg)(&reply, in, inlen);
- if (err) {
- ++remote_ierrs;
- if (kiodebug)
- remote_debug("recv error %d\n", err);
- } else if (kiodebug)
- print_msg(reply, in, inlen ? *inlen : 0, 'I');
-
- if (KGDB_CMD(reply) == type)
- return;
- ++remote_spurious;
- }
-}
-
-/*
- * Send a message. Do not wait for *any* response from the other side.
- * Some other thread of control will pick up the ack that will be generated.
- */
-static void
-m_send(type, buf, len)
- int type;
- u_char *buf;
- int len;
-{
- int err;
-
- if (!remote_instub) {
- remote_instub = 1;
- PUTCMD(KGDB_EXEC);
- }
-
- err = (*send_msg)(type, buf, len);
- if (err) {
- ++remote_ierrs;
- if (kiodebug)
- remote_debug("[send error %d] ", err);
- }
- if (kiodebug)
- print_msg(type, buf, len, 'O');
-}
-
-/*
- * 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;
-{
- int bufsize;
-
- remote_debugging = 0;
- if (sl_open(name, &send_msg, &recv_msg, &closelink, &remote_mtu,
- &bufsize))
- return;
- if (from_tty)
- printf("Remote debugging using %s\n", name);
- remote_debugging = 1;
-
- remote_cache_valid = 0;
-
- inbuffer = (u_char *)malloc(bufsize);
- outbuffer = (u_char *)malloc(bufsize);
-
- remote_signal();
-
- remote_ierrs = 0;
- remote_oerrs = 0;
- remote_spurious = 0;
-}
-
-/*
- * Close the open connection to the remote debugger. Use this when you want
- * to detach and do something else with your gdb.
- */
-void
-remote_close(from_tty)
- int from_tty;
-{
- if (!remote_debugging)
- error("remote debugging not enabled");
-
- remote_debugging = 0;
- /*
- * Take remote machine out of debug mode.
- */
- (void)PUTCMD(KGDB_KILL);
- (*closelink)();
- if (from_tty)
- printf("Ending remote debugging\n");
-
- free((char *)inbuffer);
- free((char *)outbuffer);
-}
-
-/*
- * Tell the remote machine to resume.
- */
-int
-remote_resume(step, signal)
- int step, signal;
-{
- if (!step) {
- (void)PUTCMD(KGDB_CONT);
- remote_instub = 0;
- } else {
-#ifdef NO_SINGLE_STEP
- single_step(0);
-#else
- (void)PUTCMD(KGDB_STEP);
-#endif
- }
-}
-
-/*
- * Wait until the remote machine stops, then return, storing status in STATUS
- * just as `wait' would.
- */
-int
-remote_wait(status)
- WAITTYPE *status;
-{
- int len;
-
- WSETEXIT((*status), 0);
- /*
- * When the machine stops, it will send us a KGDB_SIGNAL message,
- * so we wait for one of these.
- */
- m_recv(KGDB_SIGNAL, inbuffer, &len);
- WSETSTOP((*status), inbuffer[0]);
-}
-
-/*
- * Register context as of last remote_fetch_registers().
- */
-static char reg_cache[REGISTER_BYTES];
-
-/*
- * Read the remote registers into the block REGS.
- */
-void
-remote_fetch_registers(regs)
- char *regs;
-{
- int regno, len, rlen, ack;
- u_char *cp, *ep;
-
- regno = -1;
- do {
- outbuffer[0] = regno + 1;
- ack = m_xchg(remote_cache_valid ?
- KGDB_REG_R|KGDB_DELTA : KGDB_REG_R,
- outbuffer, 1, inbuffer, &len);
- cp = inbuffer;
- ep = cp + len;
- while (cp < ep) {
- regno = *cp++;
- rlen = REGISTER_RAW_SIZE(regno);
- bcopy((char *)cp,
- &reg_cache[REGISTER_BYTE(regno)], rlen);
- cp += rlen;
- }
- } while (ack & KGDB_MORE);
-
- remote_cache_valid = 1;
- bcopy(reg_cache, regs, REGISTER_BYTES);
-}
-
-/*
- * Store the remote registers from the contents of the block REGS.
- */
-void
-remote_store_registers(regs)
- char *regs;
-{
- u_char *cp, *ep;
- int regno, off, rlen;
-
- cp = outbuffer;
- ep = cp + remote_mtu;
-
- for (regno = 0; regno < NUM_REGS; ++regno) {
- off = REGISTER_BYTE(regno);
- rlen = REGISTER_RAW_SIZE(regno);
- if (!remote_cache_valid ||
- bcmp(&regs[off], &reg_cache[off], rlen) != 0) {
- if (cp + rlen + 1 >= ep) {
- (void)m_xchg(KGDB_REG_W,
- outbuffer, cp - outbuffer,
- (u_char *)0, (int *)0);
- cp = outbuffer;
- }
- *cp++ = regno;
- bcopy(&regs[off], cp, rlen);
- cp += rlen;
- }
- }
- if (cp != outbuffer)
- (void)m_xchg(KGDB_REG_W, outbuffer, cp - outbuffer,
- (u_char *)0, (int *)0);
- bcopy(regs, reg_cache, REGISTER_BYTES);
-}
-
-/*
- * Store a chunk of memory into the remote host.
- * 'remote_addr' is the address in the remote memory space.
- * 'cp' is the address of the buffer in our space, and 'len' is
- * the number of bytes. Returns an errno status.
- */
-int
-remote_write_inferior_memory(remote_addr, cp, len)
- CORE_ADDR remote_addr;
- u_char *cp;
- int len;
-{
- int cnt;
-
- while (len > 0) {
- cnt = min(len, remote_mtu - 4);
- bcopy((char *)&remote_addr, outbuffer, 4);
- bcopy(cp, outbuffer + 4, cnt);
- (void)m_xchg(KGDB_MEM_W, outbuffer, cnt + 4, inbuffer, &len);
-
- if (inbuffer[0])
- return inbuffer[0];
-
- remote_addr += cnt;
- cp += cnt;
- len -= cnt;
- }
- return 0;
-}
-
-/*
- * Read memory data directly from the remote machine.
- * 'remote_addr' is the address in the remote memory space.
- * 'cp' is the address of the buffer in our space, and 'len' is
- * the number of bytes. Returns an errno status.
- */
-static int
-remote_read_memory(remote_addr, cp, len)
- CORE_ADDR remote_addr;
- u_char *cp;
- int len;
-{
- int cnt, inlen;
-
- while (len > 0) {
- cnt = min(len, remote_mtu - 1);
- outbuffer[0] = cnt;
- bcopy((char *)&remote_addr, (char *)&outbuffer[1], 4);
-
- (void)m_xchg(KGDB_MEM_R, outbuffer, 5, inbuffer, &inlen);
-
- if (inbuffer[0] != 0)
- return inbuffer[0];
-
- if (cnt != inlen - 1)
- /* XXX */
- error("remote_read_memory() request botched");
-
- bcopy((char *)&inbuffer[1], (char *)cp, cnt);
-
- remote_addr += cnt;
- cp += cnt;
- len -= cnt;
- }
- return 0;
-}
-
-int
-remote_read_inferior_memory(remote_addr, cp, len)
- CORE_ADDR remote_addr;
- char *cp;
- int len;
-{
- int stat = 0;
-
- if (icache) {
- extern CORE_ADDR text_start, text_end;
- CORE_ADDR xferend = remote_addr + len;
-
- if (remote_addr < text_end && text_start < xferend) {
- /*
- * at least part of this xfer is in the text
- * space -- xfer the overlap from the exec file.
- */
- if (remote_addr >= text_start && xferend < text_end)
- return (xfer_core_file(remote_addr, cp, len));
- if (remote_addr >= text_start) {
- int i = text_end - remote_addr;
-
- if (stat = xfer_core_file(remote_addr, cp, i))
- return (stat);
- remote_addr += i;
- cp += i;
- len -= i;
- } else if (xferend <= text_end) {
- int i = xferend - text_start;
-
- len = text_start - remote_addr;
- if (stat = xfer_core_file(text_start,
- cp + len, i))
- return (stat);
- }
- }
- }
- return remote_read_memory(remote_addr, cp, len);
-}
-
-/*
- * Signal the remote machine. The remote end might be idle or it might
- * already be in debug mode -- we need to handle both case. Thus, we use
- * the framing character as the wakeup byte, and send a SIGNAL packet.
- * If the remote host is idle, the framing character will wake it up.
- * If it is in the kgdb stub, then we will get a SIGNAL reply.
- */
-static void
-remote_signal()
-{
- if (!remote_debugging)
- printf("Remote debugging not enabled.\n");
- else {
- remote_instub = 0;
- m_send(KGDB_SIGNAL, (u_char *)0, 0);
- }
-}
-
-static void
-remote_signal_command()
-{
- extern int stop_after_attach;
-
- if (!remote_debugging)
- error("Not debugging remote.");
- remote_cache_valid = 0;
- remote_signal();
- restart_remote();
-}
-
-/*
- * Print a message for debugging.
- */
-static void
-print_msg(type, buf, len, dir)
- int type;
- u_char *buf;
- int len;
- int dir;
-{
- int i;
- char *s;
-
- switch (KGDB_CMD(type)) {
- case KGDB_MEM_R: s = "memr"; break;
- case KGDB_MEM_W: s = "memw"; break;
- case KGDB_REG_R: s = "regr"; break;
- case KGDB_REG_W: s = "regw"; break;
- case KGDB_CONT: s = "cont"; break;
- case KGDB_STEP: s = "step"; break;
- case KGDB_KILL: s = "kill"; break;
- case KGDB_SIGNAL: s = "sig "; break;
- case KGDB_EXEC: s = "exec"; break;
- default: s = "unk "; break;
- }
- remote_debug("%c %c%c%c%c %s (%02x): ", dir,
- (type & KGDB_ACK) ? 'A' : '.',
- (type & KGDB_DELTA) ? 'D' : '.',
- (type & KGDB_MORE) ? 'M' : '.',
- (type & KGDB_SEQ) ? '-' : '+',
- s, type);
- if (buf)
- for (i = 0; i < len; ++i)
- remote_debug("%02x", buf[i]);
- remote_debug("\n");
-}
-
-static void
-set_remote_text_refs_command(arg, from_tty)
- char *arg;
- int from_tty;
-{
- icache = !parse_binary_operation("set remote-text-refs", arg);
-}
-
-static void
-remote_debug_command(arg, from_tty)
- char *arg;
- int from_tty;
-{
- char *name;
-
- if (kiodebug != 0 && kiodebug != stderr)
- (void)fclose(kiodebug);
-
- if (arg == 0) {
- kiodebug = 0;
- printf("Remote debugging off.\n");
- return;
- }
- if (arg[0] == '-') {
- kiodebug = stderr;
- name = "stderr";
- } else {
- kiodebug = fopen(arg, "w");
- if (kiodebug == 0) {
- printf("Cannot open '%s'.\n", arg);
- return;
- }
- name = arg;
- }
- printf("Remote debugging output routed to %s.\n", name);
-}
-
-/* ARGSUSED */
-static void
-remote_info(arg, from_tty)
- char *arg;
- int from_tty;
-{
- printf("Using %s for text references.\n",
- icache? "local executable" : "remote");
- printf("Protocol debugging is %s.\n", kiodebug? "on" : "off");
- printf("%d spurious input messages.\n", remote_spurious);
- printf("%d input errors; %d output errors; %d sequence errors.\n",
- remote_ierrs, remote_oerrs, remote_seqerrs);
-}
-
-/* VARARGS */
-static void
-remote_debug(va_alist)
- va_dcl
-{
- register char *cp;
- va_list ap;
-
- va_start(ap);
- cp = va_arg(ap, char *);
- (void)vfprintf(kiodebug, cp, ap);
- va_end(ap);
- fflush(kiodebug);
-}
-
-extern struct cmd_list_element *setlist;
-
-void
-_initialize_remote()
-{
- add_com("remote-signal", class_run, remote_signal_command,
- "If remote debugging, send interrupt signal to remote.");
- add_cmd("remote-text-refs", class_support,
- set_remote_text_refs_command,
-"Enable/disable use of local executable for text segment references.\n\
-If on, all memory read/writes go to remote.\n\
-If off, text segment reads use the local executable.",
- &setlist);
-
- add_com("remote-debug", class_run, remote_debug_command,
-"With a file name argument, enables output of remote protocol debugging\n\
-messages to said file. If file is `-', stderr is used.\n\
-With no argument, remote debugging is disabled.");
-
- add_info("remote", remote_info,
- "Show current settings of remote debugging options.");
-}
-
diff --git a/gnu/usr.bin/gdb/source.c b/gnu/usr.bin/gdb/source.c
deleted file mode 100644
index bb65e1ca9483..000000000000
--- a/gnu/usr.bin/gdb/source.c
+++ /dev/null
@@ -1,1166 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)source.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* List lines of source files for GDB, the GNU debugger.
- 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 <string.h>
-#include "defs.h"
-#include "param.h"
-#include "symtab.h"
-
-#ifdef USG
-#include <sys/types.h>
-#include <fcntl.h>
-#endif
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-
-/* Path of directories to search for source files.
- Same format as the PATH environment variable's value. */
-
-static 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;
-
-
-struct symtab *psymtab_to_symtab ();
-
-/* Set the source file default for the "list" command, specifying a
- symtab. Sigh. Behaivior 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 psytab_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, *cs_pst;
-
- 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))
- {
- sals = decode_line_spec ("main", 1);
- sal = sals.sals[0];
- free (sals.sals);
- current_source_symtab = sal.symtab;
- current_source_line = max (sal.line - 9, 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;
- }
-}
-
-static void
-directories_info ()
-{
- printf ("Source directories searched: %s\n", source_path);
-}
-
-void
-init_source_path ()
-{
- register struct symtab *s;
-
- source_path = savestring (current_directory, strlen (current_directory));
-
- /* Forget what we learned about line positions in source files;
- must check again now since files may be found in
- a different directory now. */
- for (s = symtab_list; s; s = s->next)
- if (s->line_charpos != 0)
- {
- free (s->line_charpos);
- s->line_charpos = 0;
- }
-}
-
-void
-directory_command (dirname, from_tty)
- char *dirname;
- int from_tty;
-{
- char *old = source_path;
-
- dont_repeat ();
-
- if (dirname == 0)
- {
- if (query ("Reinitialize source path to %s? ", current_directory))
- {
- init_source_path ();
- free (old);
- }
- }
- else
- {
- dirname = tilde_expand (dirname);
- make_cleanup (free, dirname);
-
- do
- {
- 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 != '/')
- name = concat (current_directory, "/", name);
- else
- name = savestring (name, p - name);
- make_cleanup (free, name);
-
- 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 = source_path;
- while (1)
- {
- if (!strncmp (p, name, len)
- && (p[len] == '\0' || p[len] == ':'))
- {
- if (from_tty)
- printf ("\"%s\" is already in the source path.\n", name);
- break;
- }
- p = index (p, ':');
- if (p != 0)
- ++p;
- else
- break;
- }
- if (p == 0)
- {
- source_path = concat (old, ":", name);
- free (old);
- old = source_path;
- }
- }
- } while (*dirname != '\0');
- if (from_tty)
- directories_info ();
- }
-}
-
-/* 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 "/"
-
- 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;
-
- 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;
- }
-
- filename = (char *) alloca (strlen (path) + strlen (string) + 2);
- fd = -1;
- for (p = path; p; p = p1 ? p1 + 1 : 0)
- {
- p1 = (char *) index (p, ':');
- if (p1)
- len = p1 - p;
- else
- len = strlen (p);
-
- strncpy (filename, p, len);
- filename[len] = 0;
- strcat (filename, "/");
- 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
- {
- *filename_opened = concat (current_directory, "/", filename);
- }
-
- return fd;
-}
-
-/* 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));
- extern int exec_mtime;
-
- if (fstat (desc, &st) < 0)
- perror_with_name (s->filename);
- if (get_exec_file (0) != 0 && exec_mtime < st.st_mtime)
- printf ("Source file is more recent than executable.\n");
-
- data = (char *) alloca (st.st_size);
- 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;
-}
-
-/* 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, line, fullname)
- struct symtab *s;
- int line;
- char **fullname;
-{
- register int desc, linenums_changed = 0;
-
- desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
- 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, line, 0);
- 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;
-}
-
-/* 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;
-
- desc = openp (source_path, 0, s->filename, O_RDONLY, 0, &s->fullname);
- if (desc < 0)
- {
- extern int errno;
- if (noerror && line + 1 == stopline)
- {
- /* can't find the file - tell user where we are anyway */
- current_source_symtab = s;
- current_source_line = line;
- first_line_listed = line;
- last_line_listed = line;
- printf_filtered ("%d\t(%s)\n", current_source_line++, s->filename);
- }
- else
- {
- if (! noerror)
- perror_with_name (s->filename);
- print_sys_errmsg (s->filename, 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);
- }
-
- current_source_symtab = s;
- current_source_line = line;
- first_line_listed = line;
-
- 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);
-}
-
-
-
-/*
- 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
-file_command(arg, from_tty)
- char *arg;
- int from_tty;
-{
- struct symtabs_and_lines sals;
- struct symtab_and_line sal;
- struct symbol *sym;
- char *arg1;
- 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 (arg == 0 || arg[0] == 0) {
- if (current_source_symtab == 0)
- select_source_symtab(0);
- else
- printf("%s\n", current_source_symtab->filename);
- return;
- }
- arg1 = arg;
- 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);
-
- /* if line was specified by address,
- 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 (sal.symtab == 0)
- {
- if (! linenum_beg)
- error ("No line number known for %s.", arg);
- else
- error ("No default source file yet. Do \"help list\".");
- }
- else
- {
- current_source_symtab = sal.symtab;
- current_source_line = sal.line;
- first_line_listed = sal.line;
- }
-}
-
-#define PUSH_STACK_SIZE 32
-static struct {
- struct symtab *symtab;
- int line;
-} push_stack[PUSH_STACK_SIZE];
-
-static unsigned int push_stack_ptr;
-
-static void
-push_to_file_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- struct symtab *cursym = current_source_symtab;
- int curline = current_source_line;
- register unsigned int i;
-
- file_command(arg, from_tty);
-
- /* if we got back, command was successful */
- i = push_stack_ptr;
- push_stack[i].symtab = cursym;
- push_stack[i].line = curline;
- push_stack_ptr = (i + 1) & (PUSH_STACK_SIZE - 1);
-}
-
-static void
-pop_file_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- register unsigned int i = push_stack_ptr;
-
- /* if there's something on the stack, pop it & clear the slot. */
- i = (i + (PUSH_STACK_SIZE - 1)) & (PUSH_STACK_SIZE - 1);
- if (push_stack[i].symtab) {
- current_source_symtab = push_stack[i].symtab;
- first_line_listed = current_source_line = push_stack[i].line;
- push_stack[i].symtab = NULL;
- push_stack_ptr = i;
- }
-}
-
-
-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 + 10, 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 - 10, 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 - 9, 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 - 5, 1), sal.line + 5, 0);
- else
- print_source_lines (sal.symtab, sal.line,
- dummy_end ? sal.line + 10 : sal_end.line + 1,
- 0);
-}
-
-/* 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;
- int 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);
- }
-}
-
-/* Commands to search the source file for a regexp. */
-
-static void
-forward_search_command (regex, from_tty)
- char *regex;
-{
- 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 = openp (source_path, 0, current_source_symtab->filename,
- O_RDONLY, 0, &current_source_symtab->fullname);
- 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 - 5, 1);
- return;
- }
- line++;
- }
-
- printf ("Expression not found\n");
- fclose (stream);
-}
-
-static void
-reverse_search_command (regex, from_tty)
- char *regex;
-{
- 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 = openp (source_path, 0, current_source_symtab->filename,
- O_RDONLY, 0, &current_source_symtab->fullname);
- 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 - 5, 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;
-}
-
-void
-_initialize_source ()
-{
- current_source_symtab = 0;
- init_source_path ();
-
- add_com ("directory", class_files, directory_command,
- "Add directory DIR to end of search path for source files.\n\
-With no argument, reset the search path to just the working directory\n\
-and forget cached info on line positions in source files.");
-
- add_info ("directories", directories_info,
- "Current search path for finding source files.");
-
- 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 ("file", class_files, file_command,
- "Select current file, function and line for display or list.\n\
-Specification can have the form:\n\
- LINENUM, to select that line in current file,\n\
- FILE:LINENUM, to select that line in that file,\n\
- FUNCTION, to select beginning of that function,\n\
- FILE:FUNCTION, to distinguish among like-named static functions.\n\
- *ADDRESS, to select the line containing that address.");
- add_com ("push-to-file", class_files, push_to_file_command,
- "Like \"file\" command but remembers current file & line on a stack.\n\
-Can later return to current file with \"pop-file\" command.\n\
-Up to 32 file positions can be pushed on stack.");
- add_com ("pop-file", class_files, pop_file_command,
- "Pops back to file position saved by most recent \"push-to-file\".\n\
-If everything has been popped from stack, command does nothing.");
-}
-
diff --git a/gnu/usr.bin/gdb/stab.def b/gnu/usr.bin/gdb/stab.def
deleted file mode 100644
index b81cda4bdc31..000000000000
--- a/gnu/usr.bin/gdb/stab.def
+++ /dev/null
@@ -1,115 +0,0 @@
-/* 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. */
-
-/* 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, 0x46, "DSLINE")
-/* Similar, for bss segment. */
-__define_stab (N_BSLINE, 0x48, "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")
diff --git a/gnu/usr.bin/gdb/stack.c b/gnu/usr.bin/gdb/stack.c
deleted file mode 100644
index 91218aae3656..000000000000
--- a/gnu/usr.bin/gdb/stack.c
+++ /dev/null
@@ -1,960 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)stack.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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. */
-
-/* modified by rjc Thu Nov 1 16:46:57 1990, fixed return_command so that
- it can return values, it still has problems when running on pmax,
- cannot write register 65 */
-
-#include <stdio.h>
-
-#include "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-#include "value.h"
-
-
-/* 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;
-
-static void select_calling_frame ();
-
-void print_frame_info ();
-
-/* 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);
-}
-
-/* Flag which will indicate when the frame has been changed
- by and "up" or "down" command. */
-static int frame_changed;
-
-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;
- 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);
- printf_filtered ("0x%x in ", fi->pc);
-
- fputs_demangled(fname, stdout, -1);
- fputs_filtered(" (...)\n", stdout);
-
- return;
- }
-
- 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 (frame_changed || source >= 0 || !sal.symtab)
- {
- if (level >= 0)
- printf_filtered ("#%-2d ", level);
- else if (frame_changed)
- printf ("#%-2d ", 0);
- if (fi->pc != sal.pc || !sal.symtab)
- printf_filtered ("0x%x in ", fi->pc);
- fputs_demangled(funname ? funname : "??", stdout, -1);
- printf_filtered(" (");
- if (args)
- {
- if (func)
- numargs = -1;
- else
- FRAME_NUM_ARGS (numargs, fi);
-
- print_frame_args (func, fi, numargs, stdout);
- }
- printf_filtered (")");
- if (sal.symtab)
- printf_filtered (" (%s line %d)", sal.symtab->filename, sal.line);
- printf_filtered ("\n");
- }
-
- if ((frame_changed || 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 (mid_statement)
- printf_filtered ("0x%x\t", fi->pc);
- print_source_lines (sal.symtab, sal.line, sal.line + 1, 1);
- }
- current_source_line = max (sal.line - 5, 1);
- }
- frame_changed = 0;
- 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;
- struct frame_info *fci;
-
- 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 Frame_unknown
- instead of guessing (this happens on the VAX, 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 (!(have_inferior_p () || have_core_file_p ()))
- error ("No inferior or core file.");
-
- frame = parse_frame_specification (addr_exp);
- if (!frame)
- error ("Invalid frame specified.");
-
- fi = get_frame_info (frame);
- get_frame_saved_regs (fi, &fsr);
- 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 ("Stack level %d, frame at 0x%x:\n pc = 0x%x",
- selected_frame_level, FRAME_FP(frame), fi->pc);
- else
- printf ("Stack frame at 0x%x:\n pc = 0x%x",
- FRAME_FP(frame), fi->pc);
-
- if (funname)
- printf (" in %s", funname);
- if (sal.symtab)
- printf (" (%s line %d)", sal.symtab->filename, sal.line);
- printf ("; saved pc 0x%x\n", FRAME_SAVED_PC (frame));
- if (calling_frame)
- printf (" called by frame at 0x%x", FRAME_FP (calling_frame));
- if (fi->next_frame && calling_frame)
- printf (",");
- if (fi->next_frame)
- printf (" caller of frame at 0x%x", fi->next_frame);
- if (fi->next_frame || calling_frame)
- printf ("\n");
-
- {
- /* Address of the argument list for this frame, or Frame_unknown. */
- CORE_ADDR arg_list = FRAME_ARGS_ADDRESS_CORRECT (fi);
- /* Number of args for this frame, or -1 if unknown. */
- int numargs;
-
- if (arg_list != Frame_unknown)
- {
- printf (" Arglist at 0x%x,", arg_list);
-
- FRAME_NUM_ARGS (numargs, fi);
- if (numargs < 0)
- printf (" args: ");
- else if (numargs == 0)
- printf (" no args.");
- else if (numargs == 1)
- printf (" 1 arg: ");
- else
- printf (" %d args: ", numargs);
- print_frame_args (func, fi, numargs, stdout);
- printf ("\n");
- }
- }
-
- /* The sp is special; what's returned isn't the save address, but
- actually the value of the previous frame's sp. */
- printf (" 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 % 4 != 0)
- printf (", ");
- else
- {
- if (count == 0)
- printf (" Saved registers:");
- printf ("\n ");
- }
- printf ("%s at 0x%x", reg_names[i], fsr.regs[i]);
- count++;
- }
- if (count)
- printf ("\n");
-}
-
-#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)
- char *count_exp;
-{
- 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--)
- current = get_prev_frame (current);
-
- /* Will stop when CURRENT reaches the top of the stack. TRAILING
- will be COUNT below it. */
- while (current)
- {
- trailing = get_prev_frame (trailing);
- current = get_prev_frame (current);
- trailing_level++;
- }
-
- count = -1;
- }
- }
- else
- count = -1;
-
- 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)
- printf_filtered ("(More stack frames follow...)\n");
-}
-
-/* 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;
- fputs_filtered (SYMBOL_NAME (sym), stream);
- fputs_filtered (" = ", stream);
- print_variable_value (sym, frame, stream);
- fprintf_filtered (stream, "\n");
- 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;
-}
-
-static void
-locals_info ()
-{
- if (!have_inferior_p () && !have_core_file_p ())
- error ("No inferior or core file.");
-
- print_frame_local_vars (selected_frame, 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;
- 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_REF_ARG
- || SYMBOL_CLASS (sym) == LOC_REGPARM)
- {
- values_printed = 1;
- fputs_filtered (SYMBOL_NAME (sym), stream);
- fputs_filtered (" = ", stream);
- print_variable_value (sym, 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 (!have_inferior_p () && !have_core_file_p ())
- error ("No inferior or core file.");
- print_frame_arg_vars (selected_frame, stdout);
-}
-
-/* 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 (!have_inferior_p () && !have_core_file_p ())
- 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 (!have_inferior_p () && ! have_core_file_p ())
- error ("No inferior or core file.");
-
- 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;
-
- frame_changed = level;
- 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_command (count_exp)
- char *count_exp;
-{
- register FRAME frame;
- int count = 1, count1;
- if (count_exp)
- count = parse_and_eval_address (count_exp);
- count1 = count;
-
- if (!have_inferior_p () && !have_core_file_p ())
- error ("No inferior or core file.");
-
- 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);
-
- print_stack_frame (selected_frame, selected_frame_level, 1);
- frame_changed++;
-}
-
-/* Select the frame down one or COUNT stack levels
- from the previously selected frame, and print it briefly. */
-
-static void
-down_command (count_exp)
- char *count_exp;
-{
- 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);
-
- print_stack_frame (selected_frame, selected_frame_level, 1);
- frame_changed--;
-}
-
-static void
-return_command (retval_exp, from_tty)
- char *retval_exp;
- int from_tty;
-{
- value return_value;
- struct symbol *thisfun = get_frame_function (selected_frame);
- FRAME_ADDR selected_frame_addr = FRAME_FP (selected_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. Note that this will not work if the selected frame
- shares it's fp with another frame. */
-
- while (selected_frame_addr != FRAME_FP (get_current_frame()))
- POP_FRAME;
-
- /* get the return value while still in this frame */
- if (retval_exp)
- return_value = parse_and_eval (retval_exp);
-
- /* Then pop that frame. */
- POP_FRAME;
-
- /* Store the return value if there was one */
-
- if (retval_exp)
- set_return_value (return_value);
-
- /* If interactive, print the frame that is now current. */
-
- if (from_tty)
- frame_command ("0", 1);
-}
-
-extern struct cmd_list_element *setlist;
-
-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 ("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 ("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.");
-
-#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/gnu/usr.bin/gdb/symmisc.c b/gnu/usr.bin/gdb/symmisc.c
deleted file mode 100644
index bb4eb50674d6..000000000000
--- a/gnu/usr.bin/gdb/symmisc.c
+++ /dev/null
@@ -1,584 +0,0 @@
-/* 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 "symtab.h"
-
-#include <stdio.h>
-#include <obstack.h>
-
-static void free_symtab ();
-
-
-/* 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 ();
- clear_breakpoints ();
- 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;
-}
-
-/* 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 type *type;
- 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);
-
- if (s->line_charpos)
- free (s->line_charpos);
- free (s->filename);
- free (s);
-}
-
-/* Convert a raw symbol-segment to a struct symtab,
- and relocate its internal pointers so that it is valid. */
-
-/* This is how to relocate one pointer, given a name for it.
- Works independent of the type of object pointed to. */
-#define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0)
-
-/* This is the inverse of RELOCATE. We use it when storing
- a core address into a slot that has yet to be relocated. */
-#define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0)
-
-/* During the process of relocation, this holds the amount to relocate by
- (the address of the file's symtab data, in core in the debugger). */
-static int relocation;
-
-#define CORE_RELOCATE(slot) \
- ((slot) += (((slot) < data_start) ? text_relocation \
- : ((slot) < bss_start) ? data_relocation : bss_relocation))
-
-#define TEXT_RELOCATE(slot) ((slot) += text_relocation)
-
-/* Relocation amounts for addresses in the program's core image. */
-static int text_relocation, data_relocation, bss_relocation;
-
-/* Boundaries that divide program core addresses into text, data and bss;
- used to determine which relocation amount to use. */
-static int data_start, bss_start;
-
-static void relocate_typevector ();
-static void relocate_blockvector ();
-static void relocate_type ();
-static void relocate_block ();
-static void relocate_symbol ();
-static void relocate_source ();
-
-/* Relocate a file's symseg so that all the pointers are valid C pointers.
- Value is a `struct symtab'; but it is not suitable for direct
- insertion into the `symtab_list' because it describes several files. */
-
-static struct symtab *
-relocate_symtab (root)
- struct symbol_root *root;
-{
- struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab));
- bzero (sp, sizeof (struct symtab));
-
- relocation = (int) root;
- text_relocation = root->textrel;
- data_relocation = root->datarel;
- bss_relocation = root->bssrel;
- data_start = root->databeg;
- bss_start = root->bssbeg;
-
- sp->filename = root->filename;
- sp->ldsymoff = root->ldsymoff;
- sp->language = root->language;
- sp->compilation = root->compilation;
- sp->version = root->version;
- sp->blockvector = root->blockvector;
- sp->typevector = root->typevector;
-
- RELOCATE (TYPEVECTOR (sp));
- RELOCATE (BLOCKVECTOR (sp));
- RELOCATE (sp->version);
- RELOCATE (sp->compilation);
- RELOCATE (sp->filename);
-
- relocate_typevector (TYPEVECTOR (sp));
- relocate_blockvector (BLOCKVECTOR (sp));
-
- return sp;
-}
-
-static void
-relocate_blockvector (blp)
- register struct blockvector *blp;
-{
- register int nblocks = BLOCKVECTOR_NBLOCKS (blp);
- register int i;
- for (i = 0; i < nblocks; i++)
- RELOCATE (BLOCKVECTOR_BLOCK (blp, i));
- for (i = 0; i < nblocks; i++)
- relocate_block (BLOCKVECTOR_BLOCK (blp, i));
-}
-
-static void
-relocate_block (bp)
- register struct block *bp;
-{
- register int nsyms = BLOCK_NSYMS (bp);
- register int i;
-
- TEXT_RELOCATE (BLOCK_START (bp));
- TEXT_RELOCATE (BLOCK_END (bp));
-
- /* These two should not be recursively processed.
- The superblock need not be because all blocks are
- processed from relocate_blockvector.
- The function need not be because it will be processed
- under the block which is its scope. */
- RELOCATE (BLOCK_SUPERBLOCK (bp));
- RELOCATE (BLOCK_FUNCTION (bp));
-
- for (i = 0; i < nsyms; i++)
- RELOCATE (BLOCK_SYM (bp, i));
-
- for (i = 0; i < nsyms; i++)
- relocate_symbol (BLOCK_SYM (bp, i));
-}
-
-static void
-relocate_symbol (sp)
- register struct symbol *sp;
-{
- RELOCATE (SYMBOL_NAME (sp));
- if (SYMBOL_CLASS (sp) == LOC_BLOCK)
- {
- RELOCATE (SYMBOL_BLOCK_VALUE (sp));
- /* We can assume the block that belongs to this symbol
- is not relocated yet, since it comes after
- the block that contains this symbol. */
- BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp;
- UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)));
- }
- else if (SYMBOL_CLASS (sp) == LOC_STATIC)
- CORE_RELOCATE (SYMBOL_VALUE (sp));
- else if (SYMBOL_CLASS (sp) == LOC_LABEL)
- TEXT_RELOCATE (SYMBOL_VALUE (sp));
- RELOCATE (SYMBOL_TYPE (sp));
-}
-
-static void
-relocate_typevector (tv)
- struct typevector *tv;
-{
- register int ntypes = TYPEVECTOR_NTYPES (tv);
- register int i;
-
- for (i = 0; i < ntypes; i++)
- RELOCATE (TYPEVECTOR_TYPE (tv, i));
- for (i = 0; i < ntypes; i++)
- relocate_type (TYPEVECTOR_TYPE (tv, i));
-}
-
-/* We cannot come up with an a priori spanning tree
- for the network of types, since types can be used
- for many symbols and also as components of other types.
- Therefore, we need to be able to mark types that we
- already have relocated (or are already in the middle of relocating)
- as in a garbage collector. */
-
-static void
-relocate_type (tp)
- register struct type *tp;
-{
- register int nfields = TYPE_NFIELDS (tp);
- register int i;
-
- RELOCATE (TYPE_NAME (tp));
- RELOCATE (TYPE_TARGET_TYPE (tp));
- RELOCATE (TYPE_FIELDS (tp));
- RELOCATE (TYPE_POINTER_TYPE (tp));
-
- for (i = 0; i < nfields; i++)
- {
- RELOCATE (TYPE_FIELD_TYPE (tp, i));
- RELOCATE (TYPE_FIELD_NAME (tp, i));
- }
-}
-
-static void
-relocate_sourcevector (svp)
- register struct sourcevector *svp;
-{
- register int nfiles = svp->length;
- register int i;
- for (i = 0; i < nfiles; i++)
- RELOCATE (svp->source[i]);
- for (i = 0; i < nfiles; i++)
- relocate_source (svp->source[i]);
-}
-
-static void
-relocate_source (sp)
- register struct source *sp;
-{
- register int nitems = sp->contents.nitems;
- register int i;
-
- RELOCATE (sp->name);
- for (i = 0; i < nitems; i++)
- TEXT_RELOCATE (sp->contents.item[i].pc);
-}
-
-/* Read symsegs from file named NAME open on DESC,
- make symtabs from them, and return a chain of them.
- These symtabs are not suitable for direct use in `symtab_list'
- because each one describes a single object file, perhaps many source files.
- `symbol_file_command' takes each of these, makes many real symtabs
- from it, and then frees it.
-
- We assume DESC is prepositioned at the end of the string table,
- just before the symsegs if there are any. */
-
-struct symtab *
-read_symsegs (desc, name)
- int desc;
- char *name;
-{
- struct symbol_root root;
- register char *data;
- register struct symtab *sp, *sp1, *chain = 0;
- register int len;
-
- while (1)
- {
- len = myread (desc, &root, sizeof root);
- if (len == 0 || root.format == 0)
- break;
- /* format 1 was ok for the original gdb, but since the size of the
- type structure changed when C++ support was added, it can no
- longer be used. Accept only format 2. */
- if (root.format != 2 ||
- root.length < sizeof root)
- error ("\nInvalid symbol segment format code");
- data = (char *) xmalloc (root.length);
- bcopy (&root, data, sizeof root);
- len = myread (desc, data + sizeof root,
- root.length - sizeof root);
- sp = relocate_symtab (data);
- RELOCATE (((struct symbol_root *)data)->sourcevector);
- relocate_sourcevector (((struct symbol_root *)data)->sourcevector);
- sp->next = chain;
- chain = sp;
- sp->linetable = (struct linetable *) ((struct symbol_root *)data)->sourcevector;
- }
-
- return chain;
-}
-
-static int block_depth ();
-void print_spaces ();
-static void print_symbol ();
-
-void
-print_symtabs (filename)
- char *filename;
-{
- FILE *outfile;
- register struct symtab *s;
- register int i, j;
- int len, line, 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 (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 %d (0x%x),",
- SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol));
- break;
-
- case LOC_CONST_BYTES:
- fprintf (outfile, "const %d hex bytes:",
- TYPE_LENGTH (SYMBOL_TYPE (symbol)));
- {
- int i;
- for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++)
- fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]);
- fprintf (outfile, ",");
- }
- break;
-
- case LOC_STATIC:
- fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol));
- break;
-
- case LOC_REGISTER:
- fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol));
- break;
-
- case LOC_ARG:
- fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol));
- break;
-
- case LOC_REF_ARG:
- fprintf (outfile, "reference arg at 0x%x,", SYMBOL_VALUE (symbol));
- break;
-
- case LOC_REGPARM:
- fprintf (outfile, "parameter register %d,", SYMBOL_VALUE (symbol));
- break;
-
- case LOC_LOCAL:
- fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol));
- break;
-
- case LOC_TYPEDEF:
- break;
-
- case LOC_LABEL:
- fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol));
- break;
-
- case LOC_BLOCK:
- fprintf (outfile, "block (object 0x%x) starting at 0x%x,",
- SYMBOL_VALUE (symbol),
- BLOCK_START (SYMBOL_BLOCK_VALUE (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;
-}
-
-/*
- * 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;
-}
-
-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/gnu/usr.bin/gdb/symseg.h b/gnu/usr.bin/gdb/symseg.h
deleted file mode 100644
index 6a61a1791a20..000000000000
--- a/gnu/usr.bin/gdb/symseg.h
+++ /dev/null
@@ -1,523 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * @(#)symseg.h 6.3 (Berkeley) 5/8/91
- */
-
-/* GDB symbol table format definitions.
- Copyright (C) 1986, 1989 Free Software Foundation, Inc.
- Hacked 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. */
-
-/* Format of GDB symbol table data.
- There is one symbol segment for each source file or
- independant compilation. These segments are simply concatenated
- to form the GDB symbol table. A zero word where the beginning
- of a segment is expected indicates there are no more segments.
-
-Format of a symbol segment:
-
- The symbol segment begins with a word containing 1
- if it is in the format described here. Other formats may
- be designed, with other code numbers.
-
- The segment contains many objects which point at each other.
- The pointers are offsets in bytes from the beginning of the segment.
- Thus, each segment can be loaded into core and its pointers relocated
- to make valid in-core pointers.
-
- All the data objects in the segment can be found indirectly from
- one of them, the root object, of type `struct symbol_root'.
- It appears at the beginning of the segment.
-
- The total size of the segment, in bytes, appears as the `length'
- field of this object. This size includes the size of the
- root object.
-
- All the object data types are defined here to contain pointer types
- appropriate for in-core use on a relocated symbol segment.
- Casts to and from type int are required for working with
- unrelocated symbol segments such as are found in the file.
-
- The ldsymaddr word is filled in by the loader to contain
- the offset (in bytes) within the ld symbol table
- of the first nonglobal symbol from this compilation.
- This makes it possible to match those symbols
- (which contain line number information) reliably with
- the segment they go with.
-
- Core addresses within the program that appear in the symbol segment
- are not relocated by the loader. They are inserted by the assembler
- and apply to addresses as output by the assembler, so GDB must
- relocate them when it loads the symbol segment. It gets the information
- on how to relocate from the textrel, datarel, bssrel, databeg and bssbeg
- words of the root object.
-
- The words textrel, datarel and bssrel
- are filled in by ld with the amounts to relocate within-the-file
- text, data and bss addresses by; databeg and bssbeg can be
- used to tell which kind of relocation an address needs. */
-
-enum language {language_c};
-
-struct symbol_root
-{
- int format; /* Data format version */
- int length; /* # bytes in this symbol segment */
- int ldsymoff; /* Offset in ld symtab of this file's syms */
- int textrel; /* Relocation for text addresses */
- int datarel; /* Relocation for data addresses */
- int bssrel; /* Relocation for bss addresses */
- char *filename; /* Name of main source file compiled */
- char *filedir; /* Name of directory it was reached from */
- struct blockvector *blockvector; /* Vector of all symbol-naming blocks */
- struct typevector *typevector; /* Vector of all data types */
- enum language language; /* Code identifying the language used */
- char *version; /* Version info. Not fully specified */
- char *compilation; /* Compilation info. Not fully specified */
- int databeg; /* Address within the file of data start */
- int bssbeg; /* Address within the file of bss start */
- struct sourcevector *sourcevector; /* Vector of line-number info */
-};
-
-/* 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 */
-
- /* 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
-/* Indicates that this type is a public baseclass of another class,
- i.e. that all its public methods are available in the derived
- class. */
-#define TYPE_FLAG_VIA_PUBLIC 1024
-/* Indicates that this type is a virtual baseclass of another class,
- i.e. that if this class is inherited more than once by another
- class, only one set of member variables will be included. */
-#define TYPE_FLAG_VIA_VIRTUAL 2048
-
-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.
- Type names specified as input are defined by symbols. */
- char *name;
- /* Length in bytes of storage for a value of this type */
- int 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. */
- 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++ */
- int *private_field_bits;
- int *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;
- /* If this is a virtual function, the offset into the vtbl-1,
- else 0. */
- int voffset;
- } *fn_fields;
-
- int *private_fn_field_bits;
- int *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;
-
- /* If this type has a base class, put it here.
- If this type is a pointer type, the chain of member pointer
- types goes here.
- Unused otherwise.
-
- Contrary to all maxims of C style and common sense, the baseclasses
- are indexed from 1 to N_BASECLASSES rather than 0 to N_BASECLASSES-1
- (i.e. BASECLASSES points to one *before* the first element of
- the array). */
- struct type **baseclasses;
-};
-
-/* 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. */
- int 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];
-};
-
-/* 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 the symbol in core. */
-
-enum address_class
-{
- LOC_UNDEF, /* Not used; catches errors */
- LOC_CONST, /* Value is constant int */
- LOC_STATIC, /* Value is at fixed address */
- LOC_REGISTER, /* Value is in register */
- LOC_ARG, /* Value is at spec'd position in arglist */
- LOC_REF_ARG, /* Value address is at spec'd position in */
- /* arglist. */
- LOC_REGPARM, /* Value is at spec'd position in register window */
- LOC_LOCAL, /* Value is at spec'd pos 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 in the code */
- LOC_BLOCK, /* Value is address of a `struct block'.
- Function names have this class. */
- LOC_EXTERNAL, /* Value is at address not in this compilation.
- This is used for .comm symbols
- and for extern symbols within functions.
- Inside GDB, this is changed to LOC_STATIC once the
- real address is obtained from a loader symbol. */
- LOC_CONST_BYTES /* Value is a constant byte-sequence. */
-};
-
-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;
- /* constant value, or address if static, or register number,
- or offset in arguments, or offset in stack frame. */
- union
- {
- long value;
- struct block *block; /* for LOC_BLOCK */
- char *bytes; /* for LOC_CONST_BYTES */
- }
- value;
-};
-
-struct partial_symbol
-{
- /* Symbol name */
- char *name;
- /* Name space code. */
- enum namespace namespace;
- /* Address class (for info_symbols) */
- enum address_class class;
- /* Associated partial symbol table */
- struct partial_symtab *pst;
- /* 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 (pst)
- in a partial symbol table, but BLOCK_START (SYMBOL_BLOCK_VALUE (st))
- in a symbol table. */
- union
- {
- long value;
- }
- value;
-};
-
-/*
- * Vectors of all partial symbols read in from file; actually declared
- * and used in dbxread.c.
- */
-extern struct psymbol_allocation_list {
- struct partial_symbol *list, *next;
- int size;
-} global_psymbols, static_psymbols;
-
-
-/* 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;
-};
diff --git a/gnu/usr.bin/gdb/symtab.c b/gnu/usr.bin/gdb/symtab.c
deleted file mode 100644
index 7b2dd7c93331..000000000000
--- a/gnu/usr.bin/gdb/symtab.c
+++ /dev/null
@@ -1,2473 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * $Header: /home/cvs/386BSD/src/gnu/usr.bin/gdb/symtab.c,v 1.2 1993/12/01 16:44:43 ats Exp $;
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)symtab.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* Symbol table lookup for the GNU debugger, 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 "defs.h"
-#include "param.h"
-#include "symtab.h"
-
-#include <obstack.h>
-#include <assert.h>
-
-char *index ();
-extern char *cplus_demangle ();
-extern struct value * value_of_this ();
-
-/* 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;
-
-/* 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;
-
-/* 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;
-
-/* Functions */
-static int find_line_common ();
-int lookup_misc_func ();
-struct partial_symtab *lookup_partial_symtab ();
-struct symtab *psymtab_to_symtab ();
-static struct partial_symbol *lookup_partial_symbol ();
-
-/* 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 = index (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.");
- s = psymtab_to_symtab (ps);
- return s;
- }
-
- 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.");
- s = psymtab_to_symtab (ps);
- return s;
- }
- }
- }
- 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;
- register char *copy;
-
- for (s = partial_symtab_list; s; s = s->next)
- if (!strcmp (name, s->filename))
- return s;
-
- 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);
- if (sym == 0 || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
- {
- 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;
-
- if (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);
-}
-
-/* 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);
-
- 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);
-
- 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);
- 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;
-{
- struct type *t;
- int i;
- char *errmsg;
-
- if (TYPE_CODE (type) != TYPE_CODE_STRUCT
- && TYPE_CODE (type) != TYPE_CODE_UNION)
- {
- terminal_ours ();
- fflush (stdout);
- fprintf (stderr, "Type ");
- type_print (type, "", stderr, -1);
- fprintf (stderr, " is not a structure or union type.\n");
- return_to_top_level ();
- }
-
- for (i = TYPE_NFIELDS (type) - 1; i >= 0; i--)
- if (!strcmp (TYPE_FIELD_NAME (type, i), name))
- return TYPE_FIELD_TYPE (type, i);
-
- terminal_ours ();
- fflush (stdout);
- fprintf (stderr, "Type ");
- type_print (type, "", stderr, -1);
- fprintf (stderr, " has no component named %s\n", name);
- return_to_top_level ();
-}
-
-/* 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;
-}
-
-/* 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;
-}
-
-/* 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;
-}
-
-/* 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;
-}
-
-
-/* Smash TYPE to be a type of pointers to TO_TYPE.
- If TO_TYPE is not permanent and has no pointer-type yet,
- record TYPE as its pointer-type. */
-
-void
-smash_to_pointer_type (type, to_type)
- struct type *type, *to_type;
-{
- int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM);
-
- bzero (type, sizeof (struct type));
- TYPE_TARGET_TYPE (type) = to_type;
- /* We assume the machine has only one representation for pointers! */
- TYPE_LENGTH (type) = sizeof (char *);
- TYPE_CODE (type) = TYPE_CODE_PTR;
-
- TYPE_MAIN_VARIANT (type) = type;
-
- if (type_permanent)
- TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
-
- if (TYPE_POINTER_TYPE (to_type) == 0
- && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM)
- || type_permanent))
- {
- TYPE_POINTER_TYPE (to_type) = type;
- }
-}
-
-/* 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);
-}
-
-/* Smash TYPE to be a type of reference to TO_TYPE.
- If TO_TYPE is not permanent and has no pointer-type yet,
- record TYPE as its pointer-type. */
-
-void
-smash_to_reference_type (type, to_type)
- struct type *type, *to_type;
-{
- int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM);
-
- bzero (type, sizeof (struct type));
- TYPE_TARGET_TYPE (type) = to_type;
- /* We assume the machine has only one representation for pointers! */
- TYPE_LENGTH (type) = sizeof (char *);
- TYPE_CODE (type) = TYPE_CODE_REF;
-
- TYPE_MAIN_VARIANT (type) = type;
-
- if (type_permanent)
- TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
-
- if (TYPE_REFERENCE_TYPE (to_type) == 0
- && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM)
- || type_permanent))
- {
- TYPE_REFERENCE_TYPE (to_type) = type;
- }
-}
-
-/* Smash TYPE to be a type of functions returning TO_TYPE.
- If TO_TYPE is not permanent and has no function-type yet,
- record TYPE as its function-type. */
-
-void
-smash_to_function_type (type, to_type)
- struct type *type, *to_type;
-{
- int type_permanent = (TYPE_FLAGS (type) & TYPE_FLAG_PERM);
-
- bzero (type, sizeof (struct type));
- TYPE_TARGET_TYPE (type) = to_type;
- TYPE_LENGTH (type) = 1;
- TYPE_CODE (type) = TYPE_CODE_FUNC;
- TYPE_NFIELDS (type) = 0;
-
- if (type_permanent)
- TYPE_FLAGS (type) |= TYPE_FLAG_PERM;
-
- if (TYPE_FUNCTION_TYPE (to_type) == 0
- && (!(TYPE_FLAGS (to_type) & TYPE_FLAG_PERM)
- || type_permanent))
- {
- TYPE_FUNCTION_TYPE (to_type) = type;
- }
-}
-
-/* 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;
- int 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 (p)
- && SYMBOL_VALUE (p) > best_pc)
- {
- best_pc = SYMBOL_VALUE (p);
- best = p;
- }
- if (best_pc == psymtab->textlow - 1)
- return 0;
- return best;
-}
-
-
-static struct symbol *lookup_block_symbol ();
-
-/* 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.
- 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)
- char *name;
- register struct block *block;
- enum namespace namespace;
- int *is_a_field_of_this;
-{
- register int i, n;
- register struct symbol *sym;
- register struct symtab *s;
- register struct partial_symtab *ps;
- register struct partial_symbol *psym;
- struct blockvector *bv;
-
- /* Search specified block and its superiors. */
-
- while (block != 0)
- {
- sym = lookup_block_symbol (block, name, namespace);
- if (sym)
- {
- block_found = block;
- 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;
- 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;
- 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 index = lookup_misc_func (name);
-
- if (index == -1)
- { /* Look for a mangled C++ name for NAME. */
- int name_len = strlen (name);
- for (index = misc_function_count; --index >= 0; )
- /* Assume orginal name is prefix of mangled name. */
- if (!strncmp (misc_function_vector[index].name, name, name_len))
- {
- char *demangled =
- cplus_demangle(misc_function_vector[index].name, -1);
- if (demangled != NULL)
- {
- int cond = strcmp (demangled, name);
- free (demangled);
- if (!cond)
- break;
- }
- }
- /* Loop terminates on no match with index == -1. */
- }
-
- if (index != -1)
- {
- ps = find_pc_psymtab (misc_function_vector[index].address);
- if (ps && !ps->readin)
- {
- s = psymtab_to_symtab (ps);
- bv = BLOCKVECTOR (s);
- block = BLOCKVECTOR_BLOCK (bv, 0);
- sym = lookup_block_symbol (block, name, namespace);
- /* sym == 0 if symbol was found in the psymtab 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:");
- */
-
- return sym;
- }
- }
- }
-
- if (psym = lookup_partial_symbol (name, 1, namespace))
- {
- ps = psym->pst;
- 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");
- 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;
- return sym;
- }
- }
-
- if (psym = lookup_partial_symbol(name, 0, namespace))
- {
- ps = psym->pst;
- 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");
- return sym;
- }
-
- 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 (name, global, namespace)
- register char *name;
- register int global;
- register enum namespace namespace;
-{
- register struct partial_symbol *start, *psym;
- register struct partial_symbol *top, *bottom, *center;
- register struct partial_symtab *pst;
- register int length;
-
- if (global)
- {
- start = global_psymbols.list;
- length = global_psymbols.next - start;
- }
- else
- {
- start = static_psymbols.list;
- length = static_psymbols.next - start;
- }
-
- if (!length)
- return (struct partial_symbol *) 0;
-
- /* Binary search. This search is guarranteed 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) == 0)
- {
- if (!top->pst->readin && SYMBOL_NAMESPACE (top) == namespace)
- return top;
- top ++;
- }
-
- return (struct partial_symbol *) 0;
-}
-
-/* Look for a symbol in block BLOCK. */
-
-static 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_REF_ARG
- || SYMBOL_CLASS (sym) == LOC_REGPARM)
- parameter_sym = sym;
- else
- return sym;
- }
- bot++;
- }
- return parameter_sym; /* Will be 0 if not found. */
-}
-
-/* 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 value;
- 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)
- {
- value.symtab = 0;
- value.line = 0;
- value.pc = pc;
- value.end = 0;
- return value;
- }
-
- 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)
- {
- value.symtab = alt_symtab;
- value.line = alt_line - 1;
- value.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0));
- value.end = alt_pc;
- }
- else
- {
- value.symtab = best_symtab;
- value.line = best_line;
- value.pc = best_pc;
- value.end = (best_end ? best_end
- : (alt_pc ? alt_pc
- : BLOCK_END (BLOCKVECTOR_BLOCK (bv, 0))));
- }
- return value;
-}
-
-/* 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 index;
- int dummy;
-
- if (symtab == 0)
- return 0;
- l = LINETABLE (symtab);
- index = find_line_common(l, line, &dummy);
- return index ? l->item[index].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 index;
- int exact_match; /* did we get an exact linenumber match */
- register CORE_ADDR prev_pc;
- CORE_ADDR last_pc;
-
- if (symtab == 0)
- return 0;
-
- l = LINETABLE (symtab);
- index = find_line_common (l, thisline, &exact_match);
- if (index)
- {
- *startptr = l->item[index].pc;
- /* If we have not seen an entry for the specified line,
- assume that means the specified line has zero bytes. */
- if (!exact_match || index == l->nitems-1)
- *endptr = *startptr;
- else
- /* Perhaps the following entry is for the following line.
- It's worth a try. */
- if (l->item[index+1].line == thisline + 1)
- *endptr = l->item[index+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;
-
- int nextline = -1;
-
- 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;
-}
-
-/* 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.
- 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 value;
- register char *p, *p1;
- register struct symtab *s;
- register struct symbol *sym;
- register CORE_ADDR pc;
- register int i;
- char *copy;
- struct symbol *sym_class;
- char *class_name, *method_name, *phys_name;
- int method_counter;
- int i1;
- struct symbol **sym_arr;
- struct type *t, *field;
- 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 *)
- malloc (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);
-
- 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;
- 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);
- if (sym_arr[i1]) i1++;
- }
- else while (t)
- {
- class_name = TYPE_NAME (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)
- {
- /* We just want the class name. In the context
- of C++, stripping off "struct " is always
- sensible. */
- if (strncmp("struct ", class_name, 7) == 0)
- class_name += 7;
- if (strncmp("union ", class_name, 6) == 0)
- class_name += 6;
-
- sym_class = lookup_symbol (class_name, 0, STRUCT_NAMESPACE, 0);
- for (method_counter = TYPE_NFN_FIELDS (SYMBOL_TYPE (sym_class)) - 1;
- method_counter >= 0;
- --method_counter)
- {
- int field_counter;
- struct fn_field *f =
- TYPE_FN_FIELDLIST1 (SYMBOL_TYPE (sym_class), method_counter);
-
- method_name = TYPE_FN_FIELDLIST_NAME (SYMBOL_TYPE (sym_class), method_counter);
- if (!strcmp (copy, method_name))
- /* Find all the fields with that name. */
- for (field_counter = TYPE_FN_FIELDLIST_LENGTH (SYMBOL_TYPE (sym_class), method_counter) - 1;
- field_counter >= 0;
- --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, 0);
- if (sym_arr[i1]) i1++;
- }
- }
- }
- if (TYPE_N_BASECLASSES (t))
- t = TYPE_BASECLASS(t, 1);
- else
- break;
- }
-
- 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 *)malloc (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 (argptr, sym_arr, physnames,
- i1, funfirstline);
- }
- else
- error ("that class does not have any method named %s",copy);
- }
- else
- 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 symbol table is loaded. Use the \"symbol-file\" command.");
- 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 guarrantee 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 symbol table is loaded. Use the \"symbol-file\" command.");
- 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)++;
- value.line = atoi (*argptr);
- switch (sign)
- {
- case plus:
- if (p == *argptr)
- value.line = 5;
- if (s == 0)
- value.line = default_line + value.line;
- break;
- case minus:
- if (p == *argptr)
- value.line = 15;
- if (s == 0)
- value.line = default_line - value.line;
- else
- value.line = 1;
- break;
- }
-
- while (*p == ' ' || *p == '\t') p++;
- *argptr = p;
- if (s == 0)
- s = default_symtab;
- value.symtab = s;
- value.pc = 0;
- values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
- values.sals[0] = value;
- values.nelts = 1;
- return values;
- }
-
- /* 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++;
- 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 function.
- If file specified, use that file's per-file block to start with. */
-
- if (s == 0)
- /* use current file as default if none is specified. */
- s = default_symtab;
-
- sym = lookup_symbol (copy, s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), 1) : 0,
- VAR_NAMESPACE, 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);
- value = find_pc_line (pc, 0);
-#ifdef PROLOGUE_FIRSTLINE_OVERLAP
- /* Convex: no need to suppress code on first line, if any */
- value.pc = pc;
-#else
- value.pc = (value.end && value.pc != pc) ? value.end : pc;
-#endif
- values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
- values.sals[0] = value;
- values.nelts = 1;
- return values;
- }
-
- if (sym)
- error ("%s is not a function.", copy);
-
- if (symtab_list == 0 && partial_symtab_list == 0)
- error ("No symbol table is loaded. Use the \"symbol-file\" command.");
-
- if ((i = lookup_misc_func (copy)) >= 0)
- {
- value.symtab = 0;
- value.line = 0;
- value.pc = misc_function_vector[i].address + FUNCTION_START_OFFSET;
- if (funfirstline)
- SKIP_PROLOGUE (value.pc);
- values.sals = (struct symtab_and_line *)malloc (sizeof (struct symtab_and_line));
- values.sals[0] = value;
- values.nelts = 1;
- return values;
- }
-
- error ("Function %s not defined.", copy);
-}
-
-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 (argptr, sym_arr, physnames, nelts, funfirstline)
- char **argptr;
- struct symbol *sym_arr[];
- char *physnames[];
- 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 *) malloc (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;
-}
-
-/* hash a symbol ("hashpjw" from Aho, Sethi & Ullman, p.436) */
-
-int
-hash_symbol(str)
- register char *str;
-{
- register unsigned int h = 0, g;
- register unsigned char c;
-
- while (c = *(unsigned char *)str++) {
- h = (h << 4) + c;
- if (g = h & 0xf0000000) {
- h = h ^ (g >> 24);
- h = h ^ g;
- }
- }
- return ((int)h);
-}
-
-/* Return the index of misc function named NAME. */
-
-int
-lookup_misc_func (name)
- register char *name;
-{
- register int i = hash_symbol(name) & (MISC_FUNC_HASH_SIZE - 1);
-
- if (misc_function_vector == 0)
- error("No symbol file");
-
- i = misc_function_hash_tab[i];
- while (i >= 0)
- {
- if (strcmp(misc_function_vector[i].name, name) == 0)
- break;
- i = misc_function_vector[i].next;
- }
- return (i);
-}
-
-/*
- * Slave routine for sources_info. Force line breaks at ,'s.
- */
-static void
-output_source_filename (name, next)
-char *name;
-int next;
-{
- static int column = 0;
-
- if (column != 0 && column + strlen (name) >= 70)
- {
- printf_filtered ("\n");
- column = 0;
- }
- else if (column != 0)
- {
- printf_filtered (" ");
- column++;
- }
- printf_filtered ("%s", name);
- column += strlen (name);
- if (next)
- {
- printf_filtered (",");
- column++;
- }
-
- if (!next) column = 0;
-}
-
-static void
-sources_info ()
-{
- register struct symtab *s;
- register struct partial_symtab *ps;
- register int column = 0;
-
- if (symtab_list == 0 && partial_symtab_list == 0)
- {
- printf ("No symbol table is loaded.\n");
- return;
- }
-
- printf_filtered ("Source files for which symbols have been read in:\n\n");
-
- for (s = symtab_list; s; s = s->next)
- output_source_filename (s->filename, s->next);
- printf_filtered ("\n\n");
-
- printf_filtered ("Source files for which symbols will be read in on demand:\n\n");
-
- for (ps = partial_symtab_list; ps; ps = ps->next)
- if (!ps->readin)
- output_source_filename (ps->filename, ps->next);
- 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. */
-
-static void sort_block_syms ();
-
-static void
-list_symbols (regexp, class)
- char *regexp;
- int class;
-{
- 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, *bound;
- char *val;
- static char *classnames[]
- = {"variable", "function", "type", "method"};
- int print_count = 0;
- int found_in_file = 0;
-
- if (regexp)
- if (val = (char *) re_comp (regexp))
- error ("Invalid regexp: %s", val);
-
- /* 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 (psym = global_psymbols.list, bound = global_psymbols.next; ;
- psym = static_psymbols.list, bound = static_psymbols.next)
- {
- for (; psym < bound; ++psym)
- {
- if (psym->pst->readin)
- continue;
-
- 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)))
- psymtab_to_symtab(psym->pst);
- }
- if (psym == static_psymbols.next)
- break;
- }
-
- /* Printout here so as to get after the "Reading in symbols"
- messages which will be generated above. */
- printf_filtered (regexp
- ? "All %ss matching regular expression \"%s\":\n"
- : "All defined %ss:\n",
- classnames[class],
- regexp);
-
- /* Here, *if* the class is correct (function only, right now), we
- should search through the misc function vector for symbols that
- match and call find_pc_psymtab on them. If find_pc_psymtab returns
- 0, don't worry about it (already read in or no debugging info). */
-
- if (class == 1)
- {
- for (i = 0; i < misc_function_count; i++)
- if (regexp == 0 || re_exec (misc_function_vector[i].name))
- {
- ps = find_pc_psymtab (misc_function_vector[i].address);
- if (ps && !ps->readin)
- psymtab_to_symtab (ps);
- }
- }
-
- 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 (!found_in_file)
- {
- printf_filtered ("\nFile %s:\n", s->filename);
- print_count += 2;
- }
- 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))))
- printf_filtered (" %s", 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 (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);
-}
-
-static void
-functions_info (regexp)
- char *regexp;
-{
- list_symbols (regexp, 1);
-}
-
-static void
-types_info (regexp)
- char *regexp;
-{
- list_symbols (regexp, 2);
-}
-
-#if 0
-/* Tiemann says: "info methods was never implemented." */
-static void
-methods_info (regexp)
- char *regexp;
-{
- list_symbols (regexp, 3);
-}
-#endif /* 0 */
-
-/* Call sort_block_syms to sort alphabetically the symbols of one block. */
-
-static int
-compare_symbols (s1, s2)
- struct symbol **s1, **s2;
-{
- /* Names that are less should come first. */
- register int 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));
-}
-
-static void
-sort_block_syms (b)
- register struct block *b;
-{
- qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
- sizeof (struct symbol *), compare_symbols);
-}
-
-/* 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;
- TYPE_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 a->startaddr >= b->startaddr && a->endaddr <= b->endaddr;
-}
-
-
-/* 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 blockvector *bv;
- struct blockvector *prev_bv = 0;
- register struct block *b, *surrounding_static_block;
- extern struct block *get_selected_block ();
- register int i, j;
- register struct symbol *sym;
- 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 = 0; 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)
- {
- struct block *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)
- {
- struct block *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);
-}
-
-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.");
- add_info ("types", types_info,
- "All types names, or those matching REGEXP.");
-#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.");
-
- obstack_init (symbol_obstack);
- obstack_init (psymbol_obstack);
-
- 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
-}
-
diff --git a/gnu/usr.bin/gdb/symtab.h b/gnu/usr.bin/gdb/symtab.h
deleted file mode 100644
index fefed6001e5f..000000000000
--- a/gnu/usr.bin/gdb/symtab.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * @(#)symtab.h 6.3 (Berkeley) 5/8/91
- */
-
-/* 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. */
-
-#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
-extern char *xmalloc ();
-extern void free ();
-
-/* 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 appears
- never to be used. */
-
-enum misc_function_type {mf_unknown = 0, mf_text, mf_data, mf_bss, mf_abs};
-
-struct misc_function
-{
- char *name;
- CORE_ADDR address;
- int next; /* index of next in this hash bucket */
- unsigned char type; /* Really enum misc_function_type. */
-};
-
-/* Address and length of the vector recording all misc function names/addresses. */
-
-struct misc_function *misc_function_vector;
-int misc_function_count;
-#define MISC_FUNC_HASH_SIZE (2048)
-int misc_function_hash_tab[MISC_FUNC_HASH_SIZE];
-
-#include "symseg.h"
-
-/* 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;
- /* 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. */
- 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;
- /* String of compilation information. May be zero. */
- char *compilation;
- /* Offset within loader symbol table
- of first local symbol for this file. */
- int ldsymoff;
- /* 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.
- */
-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;
- /* 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. */
- int textlow, texthigh;
- /* Non-zero if the symtab corresponding to this psymtab has been
- readin */
- unsigned char readin;
- /* Array of pointers to all of the partial_symtab s which this one
- depends one. Since this array can only be set to previous or
- the current (?) psymtab, this dependency tree is guarranteed 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;
-};
-
-/* 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
-
-/* 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_BYTES(symbol) (symbol)->value.bytes
-#define SYMBOL_BLOCK_VALUE(symbol) (symbol)->value.block
-#define SYMBOL_TYPE(symbol) (symbol)->type
-
-/* Some macros for bitfields. */
-#define B_SET(a,x) (a[x>>5] |= (1 << (x&31)))
-#define B_CLR(a,x) (a[x>>5] &= ~(1 << (x&31)))
-#define B_TST(a,x) (a[x>>5] & (1 << (x&31)))
-
-#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_BASECLASSES(thistype) (thistype)->baseclasses
-#define TYPE_ARG_TYPES(thistype) (thistype)->arg_types
-#define TYPE_BASECLASS(thistype,index) (thistype)->baseclasses[index]
-#define TYPE_N_BASECLASSES(thistype) (thistype)->n_baseclasses
-#define TYPE_VIA_PUBLIC(thistype) ((thistype)->flags & TYPE_FLAG_VIA_PUBLIC)
-#define TYPE_VIA_VIRTUAL(thistype) ((thistype)->flags & TYPE_FLAG_VIA_VIRTUAL)
-
-#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 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 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_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) (thistype)[n].args
-#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 > 0)
-#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1)
-
-#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)
-
-/* Functions that work on the objects described above */
-
-extern struct symtab *lookup_symtab ();
-extern struct symbol *lookup_symbol ();
-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 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 ();
-
-/* C++ stuff. */
-extern struct type *lookup_reference_type ();
-extern struct type *lookup_member_type ();
-extern struct type *lookup_class ();
-/* end of C++ stuff. */
-
-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;
-
-#ifdef LONG_LONG
-extern struct type *builtin_type_long_long;
-extern struct type *builtin_type_unsigned_long_long;
-
-#ifndef BUILTIN_TYPE_LONGEST
-#define BUILTIN_TYPE_LONGEST builtin_type_long_long
-#endif
-
-#ifndef BUILTIN_TYPE_UNSIGNED_LONGEST
-#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long_long
-#endif
-
-#else /* LONG_LONG */
-
-#ifndef BUILTIN_TYPE_LONGEST
-#define BUILTIN_TYPE_LONGEST builtin_type_long
-#endif
-
-#ifndef BUILTIN_TYPE_UNSIGNED_LONGEST
-#define BUILTIN_TYPE_UNSIGNED_LONGEST builtin_type_unsigned_long
-#endif
-
-#endif
-
-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 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 ();
diff --git a/gnu/usr.bin/gdb/utils.c b/gnu/usr.bin/gdb/utils.c
deleted file mode 100644
index 782b345c9ba1..000000000000
--- a/gnu/usr.bin/gdb/utils.c
+++ /dev/null
@@ -1,1096 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * $Header: /home/cvs/386BSD/src/gnu/usr.bin/gdb/utils.c,v 1.1 1993/06/29 09:47:42 nate Exp $;
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)utils.c 6.4 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* General utility routines 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 <ctype.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-#include <pwd.h>
-#include "defs.h"
-#ifdef HAVE_TERMIO
-#include <termio.h>
-#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
-
-extern FILE *instream;
-
-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;
-
-/* 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);
-}
-
-/* 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 ()
-{
-#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 ()
-{
- extern int remote_debugging;
-
- quit_flag = 1;
-
-#ifdef USG
- /* Restore the signal handler. */
- signal (SIGINT, request_quit);
-#endif
-
- 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;
-{
- terminal_ours (); /* Should be ok even if no inf. */
- 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);
-}
-
-/* Print an error message and exit, dumping core.
- STRING is a printf-style control string, and ARG is a corresponding
- argument. */
-void
-fatal_dump_core (string, arg)
- char *string;
- int arg;
-{
- /* "internal error" is always correct, since GDB should never dump
- core, no matter what the input. */
- fprintf (stderr, "gdb internal error: ");
- fprintf (stderr, string, arg);
- fprintf (stderr, "\n");
- signal (SIGQUIT, SIG_DFL);
- kill (getpid (), SIGQUIT);
- /* We should never get here, but just in case... */
- 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");
- }
-}
-
-/* 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;
- }
-}
-
-/* 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 || 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);
- }
-}
-
-static int lines_per_page, lines_printed, chars_per_line, chars_printed;
-
-/* Set values of page and line size. */
-static void
-set_screensize_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- char *p = arg;
- char *p1;
- int tolinesize = lines_per_page;
- int tocharsize = chars_per_line;
-
- if (p == 0)
- error_no_arg ("set screensize");
-
- while (*p >= '0' && *p <= '9')
- p++;
-
- if (*p && *p != ' ' && *p != '\t')
- error ("Non-integral argument given to \"set screensize\".");
-
- tolinesize = atoi (arg);
-
- while (*p == ' ' || *p == '\t')
- p++;
-
- if (*p)
- {
- p1 = p;
- while (*p1 >= '0' && *p1 <= '9')
- p1++;
-
- if (*p1)
- error ("Non-integral second argument given to \"set screensize\".");
-
- tocharsize = atoi (p);
- }
-
- lines_per_page = tolinesize;
- chars_per_line = tocharsize;
-}
-
-static void
-instream_cleanup(stream)
- FILE *stream;
-{
- instream = stream;
-}
-
-static void
-prompt_for_continue ()
-{
- if (ISATTY(stdin) && ISATTY(stdout))
- {
- struct cleanup *old_chain = make_cleanup(instream_cleanup, instream);
- char *cp, *gdb_readline();
-
- instream = stdin;
- immediate_quit++;
- if (cp = gdb_readline ("---Type <return> to continue---"))
- free(cp);
- chars_printed = lines_printed = 0;
- immediate_quit--;
- do_cleanups(old_chain);
- }
-}
-
-/* Reinitialize filter; ie. tell it to reset to original values. */
-
-void
-reinitialize_more_filter ()
-{
- lines_printed = 0;
- chars_printed = 0;
-}
-
-static void
-screensize_info (arg, from_tty)
- char *arg;
- int from_tty;
-{
- if (arg)
- error ("\"info screensize\" does not take any arguments.");
-
- if (!lines_per_page)
- printf ("Output more filtering is disabled.\n");
- else
- {
- printf ("Output more filtering is enabled with\n");
- printf ("%d lines per page and %d characters per line.\n",
- lines_per_page, chars_per_line);
- }
-}
-
-/* Like fputs but pause after every screenful.
- 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 || !ISATTY(stdout) || lines_per_page == 0)
- {
- 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')
- {
- 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
- {
- putc (*lineptr, stream);
- chars_printed++;
- lineptr++;
- }
-
- if (chars_printed >= chars_per_line)
- {
- chars_printed = 0;
- lines_printed++;
- /* Possible new page. */
- if (lines_printed >= lines_per_page - 1)
- prompt_for_continue ();
- }
- }
-
- if (*lineptr == '\n')
- {
- lines_printed++;
- putc ('\n', stream);
- lineptr++;
- chars_printed = 0;
- }
- }
-}
-
-/* fputs_demangled is a variant of fputs_filtered that
- demangles g++ names.*/
-
-void
-fputs_demangled (linebuffer, stream, arg_mode)
- char *linebuffer;
- FILE *stream;
-{
-#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];
- char *p;
-
- if (linebuffer == NULL)
- return;
-
- p = linebuffer;
-
- while ( *p != (char) 0 ) {
- int i = 0;
-
- /* collect non-interesting characters into buf */
- while ( *p != (char) 0 && !SYMBOL_CHAR(*p) ) {
- 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) ) {
- 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 ARG1, ARG2, and ARG3 on stdout using format FORMAT. If this
- information is going to put the amount written since the last call
- to INIIALIZE_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.
-
- 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. */
-
-void
-fprintf_filtered (stream, format, arg1, arg2, arg3, arg4, arg5, arg6)
- FILE *stream;
- char *format;
- int arg1, arg2, arg3, arg4, arg5, arg6;
-{
- static char *linebuffer = (char *) 0;
- static int line_size;
- int format_length = strlen (format);
- int numchars;
-
- /* 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. */
- (void) sprintf (linebuffer, format, arg1, arg2, arg3, arg4, arg5, arg6);
-
- fputs_filtered (linebuffer, stream);
-}
-
-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);
-}
-
-/* Print N spaces. */
-void
-print_spaces_filtered (n, stream)
- int n;
- FILE *stream;
-{
- register char *s = (char *) alloca (n + 1);
- register char *t = s;
-
- while (n--)
- *t++ = ' ';
- *t = '\0';
-
- fputs_filtered (s, stream);
-}
-
-
-#ifdef USG
-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);
-}
-
-#ifndef USG
-char *sys_siglist[32] = {
- "SIG0",
- "SIGHUP",
- "SIGINT",
- "SIGQUIT",
- "SIGILL",
- "SIGTRAP",
- "SIGIOT",
- "SIGEMT",
- "SIGFPE",
- "SIGKILL",
- "SIGBUS",
- "SIGSEGV",
- "SIGSYS",
- "SIGPIPE",
- "SIGALRM",
- "SIGTERM",
- "SIGUSR1",
- "SIGUSR2",
- "SIGCLD",
- "SIGPWR",
- "SIGWIND",
- "SIGPHONE",
- "SIGPOLL",
-};
-#endif
-
-/* 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 /* USG */
-
-#ifdef USG
-/* There is too much variation in Sys V signal numbers and names, so
- we must initialize them at runtime. */
-static char undoc[] = "(undocumented)";
-
-char *sys_siglist[NSIG];
-#endif /* USG */
-
-extern struct cmd_list_element *setlist;
-
-void
-_initialize_utils ()
-{
- int i;
- add_cmd ("screensize", class_support, set_screensize_command,
- "Change gdb's notion of the size of the output screen.\n\
-The first argument is the number of lines on a page.\n\
-The second argument (optional) is the number of characters on a line.",
- &setlist);
- add_info ("screensize", screensize_info,
- "Show gdb's current notion of the size of the output screen.");
-
- /* 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. */
- {
- int 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 = 0;
-
- val = tgetnum ("co");
- if (val >= 0)
- chars_per_line = val;
- }
- }
- }
-
-#ifdef USG
- /* Initialize signal names. */
- for (i = 0; i < NSIG; i++)
- sys_siglist[i] = undoc;
-
-#ifdef SIGHUP
- sys_siglist[SIGHUP ] = "SIGHUP";
-#endif
-#ifdef SIGINT
- sys_siglist[SIGINT ] = "SIGINT";
-#endif
-#ifdef SIGQUIT
- sys_siglist[SIGQUIT ] = "SIGQUIT";
-#endif
-#ifdef SIGILL
- sys_siglist[SIGILL ] = "SIGILL";
-#endif
-#ifdef SIGTRAP
- sys_siglist[SIGTRAP ] = "SIGTRAP";
-#endif
-#ifdef SIGIOT
- sys_siglist[SIGIOT ] = "SIGIOT";
-#endif
-#ifdef SIGEMT
- sys_siglist[SIGEMT ] = "SIGEMT";
-#endif
-#ifdef SIGFPE
- sys_siglist[SIGFPE ] = "SIGFPE";
-#endif
-#ifdef SIGKILL
- sys_siglist[SIGKILL ] = "SIGKILL";
-#endif
-#ifdef SIGBUS
- sys_siglist[SIGBUS ] = "SIGBUS";
-#endif
-#ifdef SIGSEGV
- sys_siglist[SIGSEGV ] = "SIGSEGV";
-#endif
-#ifdef SIGSYS
- sys_siglist[SIGSYS ] = "SIGSYS";
-#endif
-#ifdef SIGPIPE
- sys_siglist[SIGPIPE ] = "SIGPIPE";
-#endif
-#ifdef SIGALRM
- sys_siglist[SIGALRM ] = "SIGALRM";
-#endif
-#ifdef SIGTERM
- sys_siglist[SIGTERM ] = "SIGTERM";
-#endif
-#ifdef SIGUSR1
- sys_siglist[SIGUSR1 ] = "SIGUSR1";
-#endif
-#ifdef SIGUSR2
- sys_siglist[SIGUSR2 ] = "SIGUSR2";
-#endif
-#ifdef SIGCLD
- sys_siglist[SIGCLD ] = "SIGCLD";
-#endif
-#ifdef SIGCHLD
- sys_siglist[SIGCHLD ] = "SIGCHLD";
-#endif
-#ifdef SIGPWR
- sys_siglist[SIGPWR ] = "SIGPWR";
-#endif
-#ifdef SIGTSTP
- sys_siglist[SIGTSTP ] = "SIGTSTP";
-#endif
-#ifdef SIGTTIN
- sys_siglist[SIGTTIN ] = "SIGTTIN";
-#endif
-#ifdef SIGTTOU
- sys_siglist[SIGTTOU ] = "SIGTTOU";
-#endif
-#ifdef SIGSTOP
- sys_siglist[SIGSTOP ] = "SIGSTOP";
-#endif
-#ifdef SIGXCPU
- sys_siglist[SIGXCPU ] = "SIGXCPU";
-#endif
-#ifdef SIGXFSZ
- sys_siglist[SIGXFSZ ] = "SIGXFSZ";
-#endif
-#ifdef SIGVTALRM
- sys_siglist[SIGVTALRM ] = "SIGVTALRM";
-#endif
-#ifdef SIGPROF
- sys_siglist[SIGPROF ] = "SIGPROF";
-#endif
-#ifdef SIGWINCH
- sys_siglist[SIGWINCH ] = "SIGWINCH";
-#endif
-#ifdef SIGCONT
- sys_siglist[SIGCONT ] = "SIGCONT";
-#endif
-#ifdef SIGURG
- sys_siglist[SIGURG ] = "SIGURG";
-#endif
-#ifdef SIGIO
- sys_siglist[SIGIO ] = "SIGIO";
-#endif
-#ifdef SIGWIND
- sys_siglist[SIGWIND ] = "SIGWIND";
-#endif
-#ifdef SIGPHONE
- sys_siglist[SIGPHONE ] = "SIGPHONE";
-#endif
-#ifdef SIGPOLL
- sys_siglist[SIGPOLL ] = "SIGPOLL";
-#endif
-#endif /* USG */
-}
diff --git a/gnu/usr.bin/gdb/valarith.c b/gnu/usr.bin/gdb/valarith.c
deleted file mode 100644
index 8e76899884b8..000000000000
--- a/gnu/usr.bin/gdb/valarith.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)valarith.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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 "symtab.h"
-#include "value.h"
-#include "expression.h"
-
-
-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
- &&
- TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)
- {
- 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;
- }
-
- if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR
- &&
- VALUE_TYPE (arg1) == VALUE_TYPE (arg2))
- {
- 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;
- }
-
- 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) */
-
-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");
-
- if (TYPE_CODE (elt_type) == TYPE_CODE_FLT)
- {
- if (elt_size == sizeof (float))
- v = value_from_double (elt_type, (double) *(float *)
- (VALUE_CONTENTS (array) + elt_offs));
- else
- v = value_from_double (elt_type, *(double *)
- (VALUE_CONTENTS (array) + elt_offs));
- }
- else
- {
- int offs;
- union {int i; char c;} test;
- test.i = 1;
- if (test.c == 1)
- offs = 0;
- else
- offs = sizeof (LONGEST) - elt_size;
- v = value_from_long (elt_type, *(LONGEST *)
- (VALUE_CONTENTS (array) + elt_offs - offs));
- }
-
- 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;
-}
-
-/* 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;
- int 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 ("friend functions not implemented yet");
-
- 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+9;
- 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 call_function (argvec[0], 2 - static_memfuncp, argvec + 1);
- }
- error ("member function %s not found", tstr);
-}
-
-/* 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;
- int 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 ("friend functions not implemented yet");
-
- 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+9;
- 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 call_function (argvec[0], 1 - static_memfuncp, argvec + 1);
- }
- error ("member function %s not found", tstr);
-}
-
-/* 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);
- *(double *) VALUE_CONTENTS (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 (arg2)) >= 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);
- *(unsigned LONGEST *) VALUE_CONTENTS (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);
- *(LONGEST *) VALUE_CONTENTS (val) = v;
- }
- }
-
- return val;
-}
-
-/* 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.");
-}
-
-/* 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)
- 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))
- return (char *) value_as_long (arg1) < (char *) value_as_long (arg2);
- else
- error ("Invalid type combination in ordering comparison.");
-}
-
-/* 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.");
-}
-
-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));
-}
-
diff --git a/gnu/usr.bin/gdb/valops.c b/gnu/usr.bin/gdb/valops.c
deleted file mode 100644
index ab5652cc187a..000000000000
--- a/gnu/usr.bin/gdb/valops.c
+++ /dev/null
@@ -1,1418 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)valops.c 6.4 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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"
-
-/* 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. */
-
-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)))
- {
- VALUE_TYPE (arg2) = type;
- return arg2;
- }
- else if (VALUE_LVAL (arg2) == lval_memory)
- {
- return value_at (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
- }
- else
- error ("Invalid cast.");
-}
-
-/* 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 the value with a specified type located at specified address. */
-
-value
-value_at (type, addr)
- struct type *type;
- CORE_ADDR addr;
-{
- register value val = allocate_value (type);
- int temp;
-
- temp = read_memory (addr, VALUE_CONTENTS (val), TYPE_LENGTH (type));
- if (temp)
- {
- if (have_inferior_p () && !remote_debugging)
- print_sys_errmsg ("ptrace", temp);
- /* Actually, address between addr and addr + len was out of bounds. */
- error ("Cannot read memory: address 0x%x out of bounds.", addr);
- }
-
- VALUE_LVAL (val) = lval_memory;
- VALUE_ADDRESS (val) = addr;
-
- return val;
-}
-
-/* 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;
-
- extern CORE_ADDR find_saved_register ();
-
- 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));
- REGISTER_CONVERT_TO_RAW (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 val;
- read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- &val, sizeof val);
- modify_field (&val, (int) value_as_long (fromval),
- VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
- write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- &val, sizeof val);
- }
- 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 val;
-
- read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- &val, sizeof val);
- modify_field (&val, (int) value_as_long (fromval),
- VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
- write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
- &val, sizeof val);
- }
- 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;
- CORE_ADDR addr;
-
- /* 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++)
- {
- addr = find_saved_register (frame, regno);
- if (addr == 0)
- read_register_bytes (REGISTER_BYTE (regno),
- buffer + amount_copied,
- reg_size);
- else
- read_memory (addr, buffer + amount_copied, reg_size);
- }
-
- /* 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++)
- {
- addr = find_saved_register (frame, regno);
- if (addr == 0)
- write_register_bytes (REGISTER_BYTE (regno),
- buffer + amount_copied,
- reg_size);
- else
- write_memory (addr, buffer + amount_copied, reg_size);
- }
- }
- 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 (val) - (char *) val);
- bcopy (VALUE_CONTENTS (fromval), VALUE_CONTENTS (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 (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;
-{
- return read_var_value (var, (FRAME) 0);
-}
-
-/* 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;
-}
-
-/* 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, arg1_coerced;
-
- /* Taking the address of an array is really a no-op
- once the array is coerced to a pointer to its first element. */
- arg1_coerced = arg1;
- COERCE_ARRAY (arg1_coerced);
- if (arg1 != arg1_coerced)
- return arg1_coerced;
-
- 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;
-{
- /* Must do this before COERCE_ARRAY, otherwise an infinite loop
- will result */
- if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF)
- return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
- (CORE_ADDR) value_as_long (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 (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
- (CORE_ADDR) value_as_long (arg1));
- else if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF)
- return value_at (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)),
- (CORE_ADDR) value_as_long (arg1));
- error ("Attempt to take contents of a non-pointer value.");
-}
-
-/* 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, &buffer, len);
-#else /* stack grows upward */
- write_memory (sp, &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));
-}
-
-#ifdef NEW_CALL_FUNCTION
-
-int
-arg_stacklen(nargs, args)
- int nargs;
- value *args;
-{
- int len = 0;
-
- while (--nargs >= 0)
- len += TYPE_LENGTH(VALUE_TYPE(value_arg_coerce(args[nargs])));
-
- return len;
-}
-
-CORE_ADDR
-function_address(function, type)
- value function;
- struct type **type;
-{
- register CORE_ADDR funaddr;
- register struct type *ftype = VALUE_TYPE(function);
- register enum type_code code = TYPE_CODE(ftype);
-
- /*
- * 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);
- *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)
- *type = TYPE_TARGET_TYPE(TYPE_TARGET_TYPE(ftype));
- else
- *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);
-
- *type = builtin_type_int;
- } else
- error("Invalid data type for function to be called.");
-
- return funaddr;
-}
-
-/* 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(function, nargs, args)
- value function;
- int nargs;
- value *args;
-{
- register CORE_ADDR sp, pc;
- struct type *value_type;
- struct inferior_status inf_status;
- struct cleanup *old_chain;
- register CORE_ADDR funaddr;
- int struct_return_bytes;
- char retbuf[REGISTER_BYTES];
-
- if (!have_inferior_p())
- error("Cannot invoke functions if the inferior is not running.");
-
- save_inferior_status(&inf_status, 1);
- old_chain = make_cleanup(restore_inferior_status, &inf_status);
-
- sp = read_register(SP_REGNUM);
- funaddr = function_address(function, &value_type);
- /*
- * Are we returning a value using a structure return or a
- * normal value return?
- */
- if (using_struct_return(function, funaddr, value_type))
- struct_return_bytes = TYPE_LENGTH(value_type);
- else
- struct_return_bytes = 0;
- /*
- * Create a call sequence customized for this function and
- * the number of arguments for it.
- */
- pc = setup_dummy(sp, funaddr, nargs, args,
- struct_return_bytes, value_arg_push);
-
- /*
- * Execute the stack dummy stub. The register state will be
- * returned in retbuf. It is restored below.
- */
- run_stack_dummy(pc, retbuf);
-
- /*
- * This will restore the register context that existed before
- * we called the dummy function.
- */
- do_cleanups(old_chain);
-
- return value_being_returned(value_type, retbuf, struct_return_bytes);
-}
-#else
-
-/* 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 (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;
-
- if (!have_inferior_p ())
- error ("Cannot invoke functions if the inferior is not running.");
-
- 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
-
- {
- register CORE_ADDR funaddr;
- register struct type *ftype = VALUE_TYPE (function);
- register enum type_code code = TYPE_CODE (ftype);
-
- /* 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.");
-
- /* Are we returning a value using a structure return or a normal
- value return? */
-
- struct_return = using_struct_return (function, funaddr, value_type);
-
- /* 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, value_type);
- }
-
-#ifndef CANNOT_EXECUTE_STACK
- write_memory (start_sp, dummy1, sizeof dummy);
-
-#else
- /* Convex Unix prohibits executing in the stack segment. */
- /* Hope there is empty room at the top of the text segment. */
- {
- extern CORE_ADDR text_end;
- 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);
- }
-#endif /* CANNOT_EXECUTE_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
- }
-
- for (i = nargs - 1; i >= 0; i--)
- sp = value_arg_push (sp, args[i]);
-
-#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 this
- convention in a slightly twisted way also. */
-
- if (struct_return)
- STORE_STRUCT_RETURN (struct_addr, sp);
-
- /* Write the stack pointer. This is here because the statement above
- might fool with it */
- 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);
- }
-}
-#endif
-
-/* 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;
-#ifdef KERNELDEBUG
- extern int kernel_debugging;
-
- if (kernel_debugging)
- error("Can't stuff string constants into kernel (yet).");
-#endif
-
- /* 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);
- 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 i;
- for (i = 0; i < misc_function_count; i++)
- if (!strcmp (misc_function_vector[i].name, "malloc"))
- break;
- if (i < misc_function_count)
- val = value_from_long (builtin_type_long,
- (LONGEST) misc_function_vector[i].address);
- else
- error ("String constants require the program to have a function \"malloc\".");
- }
-
- blocklen = value_from_long (builtin_type_int, (LONGEST) (len + 1));
- val = 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;
-}
-
-static int
-type_field_index(t, name)
- register struct type *t;
- register char *name;
-{
- register int i;
-
- for (i = TYPE_NFIELDS(t); --i >= 0;)
- {
- register char *t_field_name = TYPE_FIELD_NAME (t, i);
-
- if (t_field_name && !strcmp (t_field_name, name))
- break;
- }
- return (i);
-}
-
-/* Given ARG1, 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 ARG1'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.
-
- ERR is an error message to be printed in case the field is not found. */
-
-value
-value_struct_elt (arg1, args, name, static_memfuncp, err)
- register value arg1, *args;
- char *name;
- int *static_memfuncp;
- char *err;
-{
- register struct type *t;
- register int i;
- int found = 0;
-
- struct type *baseclass;
-
- COERCE_ARRAY (arg1);
-
- t = VALUE_TYPE (arg1);
-
- /* Check for the usual case: we have pointer, target type is a struct
- * and `name' is a legal field of the struct. In this case, we can
- * just snarf the value of the field & not waste time while value_ind
- * sucks over the entire struct. */
- if (! args)
- {
- if (TYPE_CODE(t) == TYPE_CODE_PTR
- && (TYPE_CODE((baseclass = TYPE_TARGET_TYPE(t))) == TYPE_CODE_STRUCT
- || TYPE_CODE(baseclass) == TYPE_CODE_UNION)
- && (i = type_field_index(baseclass, name)) >= 0)
- {
- register int offset;
- register struct type *f = TYPE_FIELD_TYPE(baseclass, i);
-
- offset = TYPE_FIELD_BITPOS(baseclass, i) >> 3;
- if (TYPE_FIELD_BITSIZE(baseclass, i) == 0)
- return value_at(f, (CORE_ADDR)(value_as_long(arg1) + offset));
- }
- }
-
- /* Follow pointers until we get to a non-pointer. */
-
- while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
- {
- arg1 = value_ind (arg1);
- COERCE_ARRAY (arg1);
- t = VALUE_TYPE (arg1);
- }
-
- 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);
-
- baseclass = t;
-
- /* 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. */
- while (t)
- {
- i = type_field_index(t, name);
- if (i >= 0)
- return TYPE_FIELD_STATIC (t, i)
- ? value_static_field (t, name, i) : value_field (arg1, i);
-
- if (TYPE_N_BASECLASSES (t) == 0)
- break;
-
- t = TYPE_BASECLASS (t, 1);
- VALUE_TYPE (arg1) = t; /* side effect! */
- }
-
- /* C++: If it was not found as a data field, then try to
- return it as a pointer to a method. */
- t = baseclass;
- VALUE_TYPE (arg1) = t; /* side effect! */
-
- if (destructor_name_p (name, t))
- error ("use `info method' command to print out value of destructor");
-
- while (t)
- {
- for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
- {
- if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
- {
- error ("use `info method' command to print value of method \"%s\"", name);
- }
- }
-
- if (TYPE_N_BASECLASSES (t) == 0)
- break;
-
- t = TYPE_BASECLASS (t, 1);
- }
-
- error ("There is no field named %s.", name);
- return 0;
- }
-
- if (destructor_name_p (name, t))
- {
- if (!args[1])
- {
- /* destructors are a special case. */
- return (value)value_fn_field (arg1, 0,
- TYPE_FN_FIELDLIST_LENGTH (t, 0));
- }
- else
- {
- error ("destructor should not have any argument");
- }
- }
-
- /* This following loop is for methods with arguments. */
- while (t)
- {
- /* Look up as method first, because that is where we
- expect to find it first. */
- for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
- {
- struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
-
- if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
- {
- int j;
- struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
-
- found = 1;
- for (j = TYPE_FN_FIELDLIST_LENGTH (t, i) - 1; j >= 0; --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, t);
- if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
- *static_memfuncp = 1;
- return (value)value_fn_field (arg1, i, j);
- }
- }
- }
-
- if (TYPE_N_BASECLASSES (t) == 0)
- break;
-
- t = TYPE_BASECLASS (t, 1);
- VALUE_TYPE (arg1) = t; /* side effect! */
- }
-
- if (found)
- {
- error ("Structure method %s not defined for arglist.", name);
- return 0;
- }
- else
- {
- /* See if user tried to invoke data as function */
- t = baseclass;
- while (t)
- {
- i = type_field_index(t, name);
- if (i >= 0)
- return TYPE_FIELD_STATIC (t, i)
- ? value_static_field (t, name, i) : value_field (arg1, i);
-
- if (TYPE_N_BASECLASSES (t) == 0)
- break;
-
- t = TYPE_BASECLASS (t, 1);
- VALUE_TYPE (arg1) = t; /* side effect! */
- }
- error ("Structure has no component named %s.", name);
- }
-}
-
-/* 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. */
- char *dname = TYPE_NAME (type);
-
- if (name[0] == '~')
- {
- if (! TYPE_HAS_DESTRUCTOR (type))
- error ("type `%s' does not have destructor defined",
- TYPE_NAME (type));
- /* Skip past the "struct " at the front. */
- while (*dname++ != ' ') ;
- if (strcmp (dname, name+1))
- error ("destructor specification error");
- else
- 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;
- register int i;
- int found = 0;
-
- struct type *baseclass;
-
- 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");
-
- baseclass = t;
-
- while (t)
- {
- for (i = TYPE_NFIELDS (t) - 1; i >= 0; i--)
- {
- char *t_field_name = TYPE_FIELD_NAME (t, i);
- if (t_field_name && !strcmp (t_field_name, name))
- goto success;
- }
- if (TYPE_N_BASECLASSES (t) == 0)
- break;
-
- t = TYPE_BASECLASS (t, 1);
- VALUE_TYPE (arg1) = t; /* side effect! */
- }
-
- /* 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))
- goto success;
-
- while (t)
- {
- for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
- {
- if (!strcmp (TYPE_FN_FIELDLIST_NAME (t, i), name))
- return 1;
- }
-
- if (TYPE_N_BASECLASSES (t) == 0)
- break;
-
- t = TYPE_BASECLASS (t, 1);
- }
- return 0;
-
- success:
- t = VALUE_TYPE (arg1);
- while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
- {
- arg1 = value_ind (arg1);
- COERCE_ARRAY (arg1);
- t = VALUE_TYPE (arg1);
- }
-}
-
-/* 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;
- int found = 0;
- 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 >= 0; i--)
- {
- char *t_field_name = TYPE_FIELD_NAME (t, i);
- if (t_field_name && !strcmp (t_field_name, name))
- {
- 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, 1);
- }
-
- /* 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);
- 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, 1);
- }
- 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? */
-
-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
- || 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;
- char *funname = 0;
- struct block *b;
- int i;
-
- if (selected_frame == 0)
- if (complain)
- error ("no frame selected");
- else return 0;
-
- func = get_frame_function (selected_frame);
- if (func)
- funname = SYMBOL_NAME (func);
- else
- 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;
-
- sym = BLOCK_SYM (b, 0);
- if (strncmp ("$this", SYMBOL_NAME (sym), 5))
- if (complain)
- error ("current stack frame not in method");
- else return 0;
-
- return read_var_value (sym, selected_frame);
-}
diff --git a/gnu/usr.bin/gdb/valprint.c b/gnu/usr.bin/gdb/valprint.c
deleted file mode 100644
index 781eb296d391..000000000000
--- a/gnu/usr.bin/gdb/valprint.c
+++ /dev/null
@@ -1,1430 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)valprint.c 6.5 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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 "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "value.h"
-
-/* GNU software is only expected to run on systems with 32-bit integers. */
-#define UINT_MAX 0xffffffff
-
-/* 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 ();
-
-
-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
-
-/* 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;
-
- 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 repititions 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)
- {
- 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)
- {
- fputs_filtered ("\"", stream);
- in_quotes = 1;
- }
- printchar (string[i], stream, '"');
- ++things_printed;
- }
- }
-
- /* Terminate the quotes if necessary. */
- if (in_quotes)
- fputs_filtered ("\"", stream);
-
- if (force_ellipses || i < length)
- fputs_filtered ("...", stream);
-}
-
-/* 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;
-
- /* A "repeated" value really contains several values in a row.
- They are made by the @ operator.
- Print such values as if they were arrays. */
-
- 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 repititions we have detected so far. */
- unsigned int reps;
-
- if (i != 0)
- fprintf_filtered (stream, ", ");
-
- 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)
- {
- fprintf_filtered (stream, "(");
- type_print (VALUE_TYPE (val), "", stream, -1);
- fprintf_filtered (stream, ") ");
-
- /* If this is a function pointer, try to print what
- function it is pointing to by name. */
- if (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (val)))
- == TYPE_CODE_FUNC)
- {
- print_address (((int *) VALUE_CONTENTS (val))[0], stream);
- /* Return value is irrelevant except for string pointers. */
- return 0;
- }
- }
- return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
- VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
- }
-}
-
-static int prettyprint; /* Controls prettyprinting of structures. */
-int unionprint; /* Controls printing of nested unions. */
-static void scalar_print_hack();
-void (*default_scalar_print)() = scalar_print_hack;
-
-/* 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).
-
- 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;
- int len, n_baseclasses;
- struct type *elttype;
- int eltlen;
- LONGEST val;
- unsigned char c;
-
- if (pretty == Val_pretty_default)
- {
- pretty = prettyprint ? Val_prettyprint : Val_no_prettyprint;
- }
-
- QUIT;
-
- if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
- {
- fprintf_filtered (stream, "<Type not defined in this context>");
- 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;
- fprintf_filtered (stream, "{");
- /* For an array of chars, print with string syntax. */
- if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
- && format == 0)
- 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 repititions we have detected so far. */
- unsigned int reps;
-
- if (i > 0)
- fprintf_filtered (stream, ", ");
-
- 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)
- {
- 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 type *target = TYPE_TARGET_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] == '$')
- 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));
- struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type));
- char *kind = "";
-
- /* 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 = 0; i < len; i++)
- {
- int bitpos = TYPE_FIELD_BITPOS (domain, i);
- QUIT;
- if (val == bitpos)
- break;
- if (val < bitpos && i > 0)
- {
- int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target));
- /* 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
- {
- fprintf_filtered (stream, "0x%x", * (int *) valaddr);
- /* For a pointer to char or unsigned char,
- also print the string pointed to, unless pointer is null. */
-
- /* For an array of chars, print with string syntax. */
- elttype = TYPE_TARGET_TYPE (type);
- i = 0; /* Number of characters printed. */
- if (TYPE_LENGTH (elttype) == 1
- && TYPE_CODE (elttype) == TYPE_CODE_INT
- && format == 0
- && unpack_long (type, valaddr) != 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)
- {
- fprintf_filtered (stream, " ");
-
- /* Get first character. */
- if (read_memory ( (CORE_ADDR) unpack_long (type, valaddr),
- &c, 1))
- {
- /* First address out of bounds. */
- fprintf_filtered (stream, "<Address 0x%x out of bounds>",
- (* (int *) valaddr));
- break;
- }
- else
- {
- /* A real string. */
- int out_of_bounds = 0;
- 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 only fetches print_max characters, even
- though print_string might want to print more
- (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. */
- while (i < print_max)
- {
- QUIT;
- if (read_memory ((CORE_ADDR) unpack_long (type, valaddr)
- + i, &c, 1))
- {
- out_of_bounds = 1;
- force_ellipses = 0;
- break;
- }
- else if (c == '\0')
- {
- force_ellipses = 0;
- break;
- }
- else
- string[i++] = c;
- }
-
- if (i != 0)
- print_string (stream, string, i, force_ellipses);
- if (out_of_bounds)
- fprintf_filtered (stream,
- " <Address 0x%x out of bounds>",
- (*(int *) valaddr) + i);
- }
-
- fflush (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:
- fprintf_filtered (stream, "(0x%x &) = ", * (int *) valaddr);
- /* 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), * (int *) valaddr);
- val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
- VALUE_ADDRESS (val), stream, format,
- deref_ref, recurse + 1, pretty);
- }
- else
- fprintf_filtered (stream, "???");
- }
- break;
-
- case TYPE_CODE_UNION:
- if (recurse && !unionprint)
- {
- fprintf_filtered (stream, "{...}");
- break;
- }
- /* Fall through. */
- case TYPE_CODE_STRUCT:
- fprintf_filtered (stream, "{");
- len = TYPE_NFIELDS (type);
- n_baseclasses = TYPE_N_BASECLASSES (type);
- for (i = 1; i <= n_baseclasses; i++)
- {
- fprintf_filtered (stream, "\n");
- if (pretty)
- print_spaces_filtered (2 + 2 * recurse, stream);
- fputs_filtered ("<", stream);
- fputs_filtered (TYPE_NAME (TYPE_BASECLASS (type, i)), stream);
- fputs_filtered ("> = ", stream);
- val_print (TYPE_FIELD_TYPE (type, 0),
- valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8,
- 0, stream, 0, 0, recurse + 1, pretty);
- }
- if (i > 1) {
- fprintf_filtered (stream, "\n");
- print_spaces_filtered (2 + 2 * recurse, stream);
- fputs_filtered ("members of ", stream);
- fputs_filtered (TYPE_NAME (type), stream);
- fputs_filtered (": ", stream);
- }
- if (!len && i == 1)
- fprintf_filtered (stream, "<No data fields>");
- else
- {
- for (i -= 1; i < len; i++)
- {
- if (i > n_baseclasses) fprintf_filtered (stream, ", ");
- if (pretty)
- {
- fprintf_filtered (stream, "\n");
- print_spaces_filtered (2 + 2 * recurse, stream);
- }
- fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
- fputs_filtered (" = ", stream);
- /* check if static field */
- if (TYPE_FIELD_STATIC (type, i))
- {
- value v;
-
- v = value_static_field (type, TYPE_FIELD_NAME (type, i), i);
- val_print (TYPE_FIELD_TYPE (type, i),
- VALUE_CONTENTS (v), 0, stream, format,
- deref_ref, recurse + 1, pretty);
- }
- else if (TYPE_FIELD_PACKED (type, i))
- {
- char *valp = (char *) & val;
- union {int i; char c;} test;
- test.i = 1;
- if (test.c != 1)
- valp += sizeof val - TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
- val = unpack_field_as_long (type, valaddr, i);
- val_print (TYPE_FIELD_TYPE (type, i), valp, 0,
- stream, format, deref_ref, recurse + 1, pretty);
- }
- else
- {
- val_print (TYPE_FIELD_TYPE (type, i),
- valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
- 0, stream, format, deref_ref,
- recurse + 1, pretty);
- }
- }
- if (pretty)
- {
- fprintf_filtered (stream, "\n");
- print_spaces_filtered (2 * recurse, stream);
- }
- }
- fprintf_filtered (stream, "}");
- 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, "} ");
- fprintf_filtered (stream, "0x%x", address);
- break;
-
- case TYPE_CODE_INT:
- if (format)
- print_scalar_formatted (valaddr, type, format, 0, stream);
- else
- {
- (*default_scalar_print)(stream, type, unpack_long(type, valaddr));
-#ifdef notdef
- if (TYPE_LENGTH (type) == 1)
- {
- fprintf_filtered (stream, " '");
- printchar ((unsigned char) unpack_long (type, valaddr),
- stream, '\'');
- fprintf_filtered (stream, "'");
- }
-#endif
- }
- 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;
-
- default:
- error ("Invalid type code in symbol table.");
- }
- fflush (stream);
- return 0;
-}
-
-/* Print a description of a type TYPE
- in the form of a declaration of a variable named VARSTRING.
- 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_filtered (varstring, stream);
- 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_filtered (prefix, stream);
- fputs_filtered (varstring, stream);
- 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 == 1)
- {
- basetype = TYPE_BASECLASS (type, 1);
- if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
- {
- while (*name != ' ') name++;
- fprintf_filtered (stream, ": %s%s ",
- TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
- TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "");
- fputs_filtered (name + 1, stream);
- fputs_filtered (" ", stream);
- }
- n_baseclasses = TYPE_N_BASECLASSES (basetype);
- type = basetype;
- }
-
- if (type)
- {
- if (n_baseclasses != 0)
- fprintf_filtered (stream, ": ");
- for (i = 1; i <= n_baseclasses; i++)
- {
- basetype = TYPE_BASECLASS (type, i);
- if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
- {
- while (*name != ' ') name++;
- fprintf_filtered (stream, "%s%s ",
- TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
- TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "");
- fputs_filtered (name + 1, stream);
- }
- if (i < n_baseclasses)
- fprintf_filtered (stream, ", ");
- }
- fprintf_filtered (stream, " ");
- }
-}
-
-/* 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, "(");
- }
-}
-
-/* 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;
- }
-}
-
-/* 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 (TYPE_NAME (type) && (name = TYPE_NAME (type)))
- {
- while (*name != ' ') name++;
- fputs_filtered (name + 1, stream);
- fputs_filtered (" ", stream);
- }
- if (show < 0)
- fprintf_filtered (stream, "{...}");
- else
- {
- int i;
-
- 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 (! strncmp (TYPE_FIELD_NAME (type, i),
- "_vptr$", 6))
- 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_FN_FIELD_PHYSNAME (f, j)[0] == '_'
- && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
- 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");
- }
- if (len2) fprintf_filtered (stream, "\n");
- }
-
- print_spaces_filtered (level, stream);
- fprintf_filtered (stream, "}");
- }
- break;
-
- case TYPE_CODE_ENUM:
- fprintf_filtered (stream, "enum ");
- if (TYPE_NAME (type))
- {
- name = TYPE_NAME (type);
- while (*name != ' ') name++;
- fputs_filtered (name + 1, 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_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;
-
- default:
- error ("Invalid type code in symbol table.");
- }
-}
-
-static void
-scalar_print_decimal(stream, type, val)
- FILE *stream;
- struct type *type;
- LONGEST val;
-{
- fprintf_filtered(stream, TYPE_UNSIGNED(type)? "%lu":"%ld", val);
-}
-
-static void
-scalar_print_hex(stream, type, val)
- FILE *stream;
- struct type *type;
- LONGEST val;
-{
- switch (TYPE_LENGTH(type)) {
- case 1:
- fprintf_filtered (stream, "0x%02lx", val);
- break;
- case 2:
- fprintf_filtered (stream, "0x%04lx", val);
- break;
- case 4:
- fprintf_filtered (stream, "0x%08lx", val);
- break;
- default:
- fprintf_filtered (stream, "0x%lx", val);
- break;
- }
-}
-
-static void
-scalar_print_octal(stream, type, val)
- FILE *stream;
- struct type *type;
- LONGEST val;
-{
- switch (TYPE_LENGTH(type)) {
- case 1:
- fprintf_filtered (stream, "0%03lo", val);
- break;
- case 2:
- fprintf_filtered (stream, "0%06lo", val);
- break;
- case 4:
- fprintf_filtered (stream, "0%012lo", val);
- break;
- default:
- fprintf_filtered (stream, "0%lo", val);
- break;
- }
-}
-
-static void
-scalar_print_hack(stream, type, val)
- FILE *stream;
- struct type *type;
- LONGEST val;
-{
- if (TYPE_UNSIGNED(type))
- scalar_print_hex(stream, type, val);
- else
- scalar_print_decimal(stream, type, val);
-}
-
-static void
-set_maximum_command (arg)
- char *arg;
-{
- if (!arg) error_no_arg ("value for maximum elements to print");
- print_max = parse_and_eval_address (arg);
- if (print_max == 0)
- print_max = UINT_MAX;
-}
-
-static void
-set_base_command(arg)
- char *arg;
-{
- int base;
-
- if (!arg)
- base = 0;
- else
- base = parse_and_eval_address (arg);
- switch (base) {
- default:
- default_scalar_print = scalar_print_hack;
- break;
- case 8:
- default_scalar_print = scalar_print_octal;
- break;
- case 10:
- default_scalar_print = scalar_print_decimal;
- break;
- case 16:
- default_scalar_print = scalar_print_hex;
- break;
- }
-}
-
-static void
-set_prettyprint_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- prettyprint = parse_binary_operation ("set prettyprint", arg);
-}
-
-static void
-set_unionprint_command (arg, from_tty)
- char *arg;
- int from_tty;
-{
- unionprint = parse_binary_operation ("set unionprint", arg);
-}
-
-format_info (arg, from_tty)
- char *arg;
- int from_tty;
-{
- if (arg)
- error ("\"info format\" does not take any arguments.");
- printf ("Prettyprinting of structures is %s.\n",
- prettyprint ? "on" : "off");
- printf ("Printing of unions interior to structures is %s.\n",
- unionprint ? "on" : "off");
- if (print_max == UINT_MAX)
- printf_filtered
- ("There is no maximum number of array elements printed.\n");
- else
- printf_filtered
- ("The maximum number of array elements printed is %d.\n", print_max);
-}
-
-extern struct cmd_list_element *setlist;
-
-void
-_initialize_valprint ()
-{
- add_cmd ("base", class_support, set_base_command,
- "Change default integer print radix to 8, 10 or 16\n\
-No args returns to the ad-hoc default of `16' for unsigned values\n\
-and `10' otherwise.",
- &setlist);
- add_cmd ("array-max", class_vars, set_maximum_command,
- "Set NUMBER as limit on string chars or array elements to print.\n\
-\"set array-max 0\" causes there to be no limit.",
- &setlist);
-
- add_cmd ("prettyprint", class_support, set_prettyprint_command,
- "Turn prettyprinting of structures on and off.",
- &setlist);
- add_alias_cmd ("pp", "prettyprint", class_support, 1, &setlist);
-
- add_cmd ("unionprint", class_support, set_unionprint_command,
- "Turn printing of unions interior to structures on and off.",
- &setlist);
-
- add_info ("format", format_info,
- "Show current settings of data formatting options.");
-
- /* Give people the defaults which they are used to. */
- prettyprint = 0;
- unionprint = 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";
-}
-
diff --git a/gnu/usr.bin/gdb/value.h b/gnu/usr.bin/gdb/value.h
deleted file mode 100644
index 07dd8e840eb7..000000000000
--- a/gnu/usr.bin/gdb/value.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* 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. */
-
-/*
- * 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;
- /* Actual contents of the value. For use of this value; setting
- it uses the stuff above. */
- long contents[1];
- };
-
-typedef struct value *value;
-
-#define VALUE_TYPE(val) (val)->type
-#define VALUE_CONTENTS(val) ((char *) (val)->contents)
-#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
-
-/* If ARG is an array, convert it to a pointer.
- If ARG is an enum, convert it to an integer.
-
- References are dereferenced. */
-
-#define COERCE_ARRAY(arg) \
-{ if (TYPE_CODE ( VALUE_TYPE (arg)) == TYPE_CODE_REF) \
- arg = value_ind (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_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;
-};
-
-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_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_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 value_cast ();
-value value_zero ();
-value value_repeat ();
-value value_subscript ();
-
-value call_function ();
-value value_being_returned ();
-int using_struct_return ();
-
-value evaluate_expression ();
-value evaluate_type ();
-value parse_and_eval ();
-value parse_to_comma_and_eval ();
-
-value access_value_history ();
-value value_of_internalvar ();
-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 ();
-int binop_user_defined_p ();
-int unop_user_defined_p ();
-
-void read_register_bytes ();
-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
- };
-
diff --git a/gnu/usr.bin/gdb/values.c b/gnu/usr.bin/gdb/values.c
deleted file mode 100644
index 93a291112a65..000000000000
--- a/gnu/usr.bin/gdb/values.c
+++ /dev/null
@@ -1,1059 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)values.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/* 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 "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "value.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 */
-
-
-/* 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;
-
- /* If the type we want had no definition in the file it first
- * appeared in, it will be marked a `stub'. The real definition
- * probably appeared later so try to find it. */
- if (TYPE_FLAGS(type) & TYPE_FLAG_STUB)
- {
- register char *cp;
- register struct symbol *sym;
- extern char *index();
-
- if (cp = index(TYPE_NAME(type), ' '))
- ++cp;
- else
- cp = TYPE_NAME(type);
-
- sym = lookup_symbol(cp, 0, STRUCT_NAMESPACE, 0);
-
- if (sym && TYPE_CODE(SYMBOL_TYPE(sym)) == TYPE_CODE(type))
- bcopy (SYMBOL_TYPE (sym), type, sizeof (*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;
- 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;
- 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);
- 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);
- bcopy (VALUE_CONTENTS (arg), VALUE_CONTENTS (val),
- TYPE_LENGTH (VALUE_TYPE (arg))
- * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
- return val;
-}
-
-/* Access to the value history. */
-
-/* Record a new value in the value history.
- Returns the absolute history index of the entry. */
-
-int
-record_latest_value (val)
- value val;
-{
- int i;
- double foo;
-
- /* 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) {
- foo = 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';
- }
-}
-
-/* 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);
- 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)
- {
- printf ("Debugger convenience variables:\n\n");
- 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");
-}
-
-/* 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;
-{
- 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;
-}
-
-/* Unpack raw data (copied from debugee) 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.
-
- 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))
- return * (float *) valaddr;
-
- if (len == sizeof (double))
- return * (double *) valaddr;
- }
- else if (code == TYPE_CODE_INT && nosign)
- {
- if (len == sizeof (char))
- return * (unsigned char *) valaddr;
-
- if (len == sizeof (short))
- return * (unsigned short *) valaddr;
-
- if (len == sizeof (int))
- return * (unsigned int *) valaddr;
-
- if (len == sizeof (long))
- return * (unsigned long *) valaddr;
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- return * (unsigned long long *) valaddr;
-#endif
- }
- else if (code == TYPE_CODE_INT)
- {
- if (len == sizeof (char))
- return * (char *) valaddr;
-
- if (len == sizeof (short))
- return * (short *) valaddr;
-
- if (len == sizeof (int))
- return * (int *) valaddr;
-
- if (len == sizeof (long))
- return * (long *) valaddr;
-
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- return * (long long *) valaddr;
-#endif
- }
- else if (code == TYPE_CODE_PTR
- || code == TYPE_CODE_REF)
- {
- if (len == sizeof (char *))
- return (CORE_ADDR) * (char **) valaddr;
- }
- else if (code == TYPE_CODE_MEMBER)
- error ("not implemented: member types in unpack_long");
-
- error ("Value not integer or pointer.");
-}
-
-/* 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. */
-
-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))
- return * (float *) valaddr;
-
- if (len == sizeof (double))
- {
- /* Some machines require doubleword alignment for doubles.
- This code works on them, and on other machines. */
- double temp;
- bcopy ((char *) valaddr, (char *) &temp, sizeof (double));
- return temp;
- }
- }
- else if (code == TYPE_CODE_INT && nosign)
- {
- if (len == sizeof (char))
- return * (unsigned char *) valaddr;
-
- if (len == sizeof (short))
- return * (unsigned short *) valaddr;
-
- if (len == sizeof (int))
- return * (unsigned int *) valaddr;
-
- if (len == sizeof (long))
- return * (unsigned long *) valaddr;
-
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- return * (unsigned long long *) valaddr;
-#endif
- }
- else if (code == TYPE_CODE_INT)
- {
- if (len == sizeof (char))
- return * (char *) valaddr;
-
- if (len == sizeof (short))
- return * (short *) valaddr;
-
- if (len == sizeof (int))
- return * (int *) valaddr;
-
- if (len == sizeof (long))
- return * (long *) valaddr;
-
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- return * (long long *) valaddr;
-#endif
- }
-
- error ("Value not floating number.");
- /* NOTREACHED */
- return (double) 0; /* To silence compiler warning. */
-}
-
-/* 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;
-{
- register value v;
- register struct type *type = TYPE_FIELD_TYPE (VALUE_TYPE (arg1), fieldno);
- register int offset;
-
- /* Handle packed fields */
-
- offset = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) / 8;
- if (TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno))
- {
- v = value_from_long (type,
- unpack_field_as_long (VALUE_TYPE (arg1),
- VALUE_CONTENTS (arg1),
- fieldno));
- VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (VALUE_TYPE (arg1), fieldno) % 8;
- VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (VALUE_TYPE (arg1), fieldno);
- }
- else
- {
- v = allocate_value (type);
- bcopy (VALUE_CONTENTS (arg1) + offset,
- VALUE_CONTENTS (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;
-}
-
-value
-value_fn_field (arg1, fieldno, subfieldno)
- register value arg1;
- register int fieldno;
-{
- 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);
- 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.
- 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.
- TYPE is the basetype which first provides the virtual function table. */
-value
-value_virtual_fn_field (arg1, f, j, type)
- value arg1;
- struct fn_field *f;
- int j;
- struct type *type;
-{
- /* 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 vfn, vtbl;
- value vi = value_from_long (builtin_type_int,
- (LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
- VALUE_TYPE (arg1) = TYPE_VPTR_BASETYPE (type);
-
- /* 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 (type) < 0)
- TYPE_VPTR_FIELDNO (type)
- = fill_in_vptr_fieldno (type);
-
- /* 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 (type)));
-
- /* 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. */
- vfn = value_field (value_subscript (vtbl, vi), 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;
-
- if (fieldno < 0)
- {
- register struct type *t = type;
- /* Look for static field. */
- while (t)
- {
- int i;
- for (i = TYPE_NFIELDS (t) - 1; i >= 0; 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");
- }
- t = TYPE_BASECLASSES (t) ? TYPE_BASECLASS (t, 1) : 0;
- }
-
- t = type;
-
- if (destructor_name_p (fieldname, t))
- error ("use `info method' command to print out value of destructor");
-
- while (t)
- {
- int i, j;
-
- for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; i--)
- {
- if (! strcmp (TYPE_FN_FIELDLIST_NAME (t, i), fieldname))
- {
- error ("use `info method' command to print value of method \"%s\"", fieldname);
- }
- }
- t = TYPE_BASECLASSES (t) ? TYPE_BASECLASS (t, 1) : 0;
- }
- error("there is no field named %s", fieldname);
- }
-
- found:
-
- sym = lookup_symbol (TYPE_FIELD_STATIC_PHYSNAME (type, fieldno),
- 0, VAR_NAMESPACE, 0);
- if (! sym) error ("Internal error: could not find physical static variable named %s", TYPE_FIELD_BITSIZE (type, fieldno));
-
- type = TYPE_FIELD_TYPE (type, fieldno);
- v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
- return v;
-}
-
-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);
-
- /* 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);
-}
-
-/* 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 (val) = num;
- else if (len == sizeof (short))
- * (short *) VALUE_CONTENTS (val) = num;
- else if (len == sizeof (int))
- * (int *) VALUE_CONTENTS (val) = num;
- else if (len == sizeof (long))
- * (long *) VALUE_CONTENTS (val) = num;
-#ifdef LONG_LONG
- else if (len == sizeof (long long))
- * (long long *) VALUE_CONTENTS (val) = num;
-#endif
- else
- error ("Integer type encountered with unexpected data length.");
- }
- else
- error ("Unexpected type encountered for integer constant.");
-
- 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 (val) = num;
- else if (len == sizeof (double))
- * (double *) VALUE_CONTENTS (val) = num;
- else
- error ("Floating type encountered with unexpected data length.");
- }
- else
- error ("Unexpected type encountered for floating constant.");
-
- return val;
-}
-
-/* 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;
-{
- register value val;
-
- if (struct_return)
- return value_at (valtype, EXTRACT_STRUCT_VALUE_ADDRESS (retbuf));
-
- val = allocate_value (valtype);
- EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS (val));
-
- return val;
-}
-
-/* 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 */
-
-struct block *block_for_pc ();
-
-int
-using_struct_return (function, funcaddr, value_type)
- value function;
- CORE_ADDR funcaddr;
- struct type *value_type;
-{
- register enum type_code code = TYPE_CODE (value_type);
-
- if (code == TYPE_CODE_STRUCT ||
- code == TYPE_CODE_UNION ||
- code == TYPE_CODE_ARRAY)
- {
- struct block *b = block_for_pc (funcaddr);
-
- if (!(BLOCK_GCC_COMPILED (b) && TYPE_LENGTH (value_type) < 8))
- return 1;
- }
-
- 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));
- char regbuf[REGISTER_BYTES];
- double dbuf;
- LONGEST lbuf;
-
- if (code == TYPE_CODE_STRUCT
- || code == TYPE_CODE_UNION)
- error ("Specifying a struct or union return value is not supported.");
-
- if (code == TYPE_CODE_FLT)
- {
- dbuf = value_as_double (val);
-
- STORE_RETURN_VALUE (VALUE_TYPE (val), &dbuf);
- }
- else
- {
- lbuf = value_as_long (val);
- STORE_RETURN_VALUE (VALUE_TYPE (val), &lbuf);
- }
-}
-
-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 GDB:\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", value_history_info, 0);
-}
diff --git a/gnu/usr.bin/gdb/version.c b/gnu/usr.bin/gdb/version.c
deleted file mode 100644
index 2f3dd8504301..000000000000
--- a/gnu/usr.bin/gdb/version.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Define the current version number of GDB.
- 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. */
-
-char *version = "3.5";
diff --git a/gnu/usr.bin/gdb/wait.h b/gnu/usr.bin/gdb/wait.h
deleted file mode 100644
index c431cb6a47a9..000000000000
--- a/gnu/usr.bin/gdb/wait.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*-
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)wait.h 6.3 (Berkeley) 5/8/91
- */
-
-/* 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 WEXITSTATUS(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
-
-#include <sys/wait.h>
-
-#define WAITTYPE union wait
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(w) (w).w_retcode
-#endif
-#ifndef WSTOPSIG
-#define WSTOPSIG(w) (w).w_stopsig
-#endif
-#ifndef WCOREDUMP
-#define WCOREDUMP(w) (w).w_coredump
-#endif
-#ifndef WTERMSIG
-#define WTERMSIG(w) (w).w_termsig
-#endif
-#ifndef WSETEXIT
-#define WSETEXIT(w, status) ((w).w_status = (status))
-#endif
-#ifndef WSETSTOP
-#define WSETSTOP(w,sig) \
- ((w).w_stopsig = (sig), (w).w_coredump = 0, (w).w_termsig = 0177)
-#endif
-
-#endif
diff --git a/gnu/usr.bin/gdb/xgdb/Makefile b/gnu/usr.bin/gdb/xgdb/Makefile
deleted file mode 100644
index 72c53598dd27..000000000000
--- a/gnu/usr.bin/gdb/xgdb/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-# %W% (Berkeley) %G%
-
-.include "../config/Makefile.$(MACHINE)"
-
-PROG= xgdb
-SRCS= xgdb.c xgdbinit.c
-GDBOBJS+= $(CONFIGSRCS:R:S/$/.o/g) \
- blockframe.o breakpoint.o command.o copying.o core.o \
- cplus-dem.o dbxread.o environ.o eval.o expprint.o \
- expread.o findvar.o infcmd.o inflow.o infrun.o \
- main.o obstack.o printcmd.o regex.o remote.o \
- remote-sl.o source.o stack.o symmisc.o symtab.o \
- utils.o valarith.o valops.o valprint.o values.o \
- version.o \
- funmap.o history.o keymaps.o readline.o
-CFLAGS+= -I.. -I$(.CURDIR)/.. -I$(.CURDIR)/../config \
- -DHAVE_VPRINTF -DVI_MODE -DKERNELDEBUG
-LDFLAGS+= -L/usr/lib/X11
-LDADD+= $(GDBOBJS:S/^/..\//g) -lXaw -lXmu -lXt -lXext -lX11 -ltermcap
-NOMAN= noman
-
-.include "../../Makefile.inc"
-.include <bsd.prog.mk>
-
-#
-# Generate the constructor
-#
-xgdbinit.c: ../init.c xgdb.c
- -(sed -e '/^}$$/d' ../init.c; \
- egrep -h '^_initialize_[^ ]* *\(\)' $(.CURDIR)/xgdb.c; \
- echo ';}') > xgdbinit.c
-
-CLEANFILES+= xgdbinit.c
diff --git a/gnu/usr.bin/gdb/xgdb/xgdb.c b/gnu/usr.bin/gdb/xgdb/xgdb.c
deleted file mode 100644
index c480f42b251e..000000000000
--- a/gnu/usr.bin/gdb/xgdb/xgdb.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
- *
- * static char rcsid[] = "$Header: /home/cvs/386BSD/src/gnu/usr.bin/gdb/xgdb/xgdb.c,v 1.1 1993/06/29 09:48:26 nate Exp $";
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)xgdb.c 6.3 (Berkeley) 5/8/91";
-#endif /* not lint */
-
-/*
- * Interface from GDB to X windows. Copyright (C) 1987 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!
- */
-
-/*
- * Original version was contributed by Derek Beatty, 30 June 87.
- * This version is essentially a re-write of the original by Van
- * Jacobson (van@helios.ee.lbl.gov), Nov, 90.
- */
-
-#include "defs.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-
-extern int stop_breakpoint;
-
-#include <X11/IntrinsicP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/AsciiSink.h>
-#include <X11/Xaw/AsciiText.h>
-#include <X11/Xaw/Box.h>
-#include <X11/Xaw/Command.h>
-#include <X11/Xaw/Label.h>
-#include <X11/Xaw/Paned.h>
-#include <X11/Xaw/Text.h>
-
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/file.h>
-#include <sys/errno.h>
-
-extern int errno;
-extern char *getenv();
-extern char *malloc();
-extern void bcopy();
-extern int select();
-
-extern int get_filename_and_charpos();
-extern int source_line_charpos();
-extern int source_charpos_line();
-extern void execute_command();
-extern void error_no_arg();
-extern void add_com();
-
-/* The X display where the window appears. */
-
-static char *displayname;
-static Display *display;
-
-static XtAppContext app_context;
-
-/* Windows manipulated by this package. */
-
-static Widget main_widget;
-static Widget containing_widget;
-static Widget source_name_widget;
-static Widget source_text_widget;
-static Widget button_box_widget;
-
-/* Source text display. */
-
-static struct frame_info *last_fi;
-static CORE_ADDR last_pc;
-static struct symtab *last_cur_symtab;
-static int last_cur_line;
-
-static int source_window_line;
-static char *source_window_file;
-static struct symtab *source_window_symtab;
-
-static char version_label[64];
-extern char *version;
-
-/* Forward declarations */
-
-static Widget create_text_widget();
-
-static int
-safe_strcmp(a, b)
- register char *a, *b;
-{
- register int i;
-
- if (a == b)
- return (0);
- if (!a && b)
- return (1);
- if (a && !b)
- return (-1);
- return (strcmp(a, b));
-}
-
-
-/* Display an appropriate piece of source code in the source window. */
-
-void
-xgdb_display_source()
-{
- char *filename = NULL;
- struct symtab_and_line get_selected_frame_sal();
- struct symtab_and_line sal;
- struct frame_info *fi;
-
- /* Do nothing if called before we are initialized */
-
- if (!containing_widget)
- return;
-
- /*
- * Figure out what to display (the appropriate hooks to tell
- * us don't exist so we guess): If there's a current frame
- * and it or its pc changed from the last time we were here,
- * display appropriate source line. Otherwise if the current
- * source symtab or line is different, display that line.
- * Otherwise nothing changed so leave the display alone.
- */
- fi = get_frame_info(selected_frame);
- if (fi && (fi != last_fi || fi->pc != last_pc)) {
- last_fi = fi;
- last_pc = fi->pc;
- sal = find_pc_line(fi->pc, fi->next_frame);
- if (sal.symtab == NULL) { /* XXX */
- sal.symtab = current_source_symtab;
- sal.line = current_source_line;
- }
- current_source_symtab = sal.symtab;
- current_source_line = sal.line;
- } else if (current_source_symtab != last_cur_symtab ||
- current_source_line != last_cur_line) {
- sal.symtab = last_cur_symtab = current_source_symtab;
- sal.line = last_cur_line = current_source_line;
- } else
- return;
- /*
- * Do a path search and get the exact filename of this source file.
- * Also scan it and find its source lines if not already done.
- */
- if (sal.symtab && filename == NULL) {
- if (get_filename_and_charpos(sal.symtab, sal.line, &filename))
- /* line numbers may have changed - force highlight */
- source_window_line = -1;
- }
-
- /*
- * If the source window is wrong, destroy it and make a new one.
- */
- if (safe_strcmp(filename, source_window_file)) {
- Arg args[1];
- Widget src = XawTextGetSource(source_text_widget);
-
- if (filename) {
- XtSetArg(args[0], XtNstring, filename);
- XtSetValues(src, args, XtNumber(args));
- args[0].name = XtNlabel;
- XtSetValues(source_name_widget, args, XtNumber(args));
- } else {
- XtSetArg(args[0], XtNstring, "/dev/null");
- XtSetValues(src, args, XtNumber(args));
- XtSetArg(args[0], XtNlabel, "");
- XtSetValues(source_name_widget, args, XtNumber(args));
- }
- if (source_window_file)
- free(source_window_file);
- source_window_file = filename;
- source_window_line = sal.line + 1; /* force highlight */
- }
- if (sal.symtab && source_window_line != sal.line) {
- /*
- * Update display and cursor positions as necessary.
- * Cursor should be placed on line sal.line.
- */
- XawTextPosition l, r;
-
- source_window_symtab = sal.symtab;
- source_window_line = sal.line;
- l = source_line_charpos(source_window_symtab, sal.line);
- r = source_line_charpos(source_window_symtab, sal.line + 1);
- if (r < l)
- r = l + 1;
- XawTextSetSelection(source_text_widget, l, r);
- XawTextScrollToLine(source_text_widget, l, 10, 3);
- XawTextSetInsertionPoint(source_text_widget, l);
- }
-}
-
-
-/*
- * Handlers for buttons.
- */
-
-static int
-current_lineno()
-{
- XawTextPosition start, finish;
-
- XawTextGetSelectionPos(source_text_widget, &start, &finish);
- if (start >= finish)
- start = XawTextGetInsertionPoint(source_text_widget);
-
- return (source_charpos_line(source_window_symtab, start));
-}
-
-static char *
-append_selection(cp)
- char *cp;
-{
- int len;
- XawTextPosition l, r;
-
- XawTextGetSelectionPos(source_text_widget, &l, &r);
- if ((len = r - l) > 0) {
- Widget src = XawTextGetSource(source_text_widget);
-
- while (len > 0) {
- XawTextBlock tb;
-
- XawTextSourceRead(src, l, &tb, len);
- bcopy(tb.ptr, cp, tb.length);
- cp += tb.length;
- len -= tb.length;
- }
- if (cp[-1] == 0)
- --cp;
- }
- return (cp);
-}
-
-static char *
-append_selection_word(cp)
- register char *cp;
-{
- register int len;
- XawTextPosition l, r;
- XawTextBlock tb;
- register char c;
- register Widget src = XawTextGetSource(source_text_widget);
-
- XawTextGetSelectionPos(source_text_widget, &l, &r);
- if ((len = r - l) <= 0) {
- l = XawTextGetInsertionPoint(source_text_widget);
- len = 128; /* XXX */
-
- /* might have clicked in middle of word -- back up to start */
- for ( ; l > 0; --l) {
- XawTextSourceRead(src, l - 1, &tb, 1);
- c = tb.ptr[0];
- if (! isalnum(c) && c != '_' && c != '$')
- break;
- }
- }
- while (len > 0) {
- char *sp;
- int i;
-
- XawTextSourceRead(src, l, &tb, len);
- for (sp = tb.ptr, i = tb.length; --i >= 0; ) {
- c = *sp++;
- if (!isalnum(c) && c != '_' && c != '$')
- return (cp);
- *cp++ = c;
- }
- len -= tb.length;
- }
- return (cp);
-}
-
-static char *
-append_selection_expr(cp)
- char *cp;
-{
- int len;
- XawTextPosition l, r;
- Widget src = XawTextGetSource(source_text_widget);
- XawTextBlock tb;
- char *sp;
- char c;
-
- XawTextGetSelectionPos(source_text_widget, &l, &r);
- if (r > l)
- return (append_selection(cp));
-
- l = XawTextGetInsertionPoint(source_text_widget);
-
- /* might have clicked in middle of word -- back up to start */
- for ( ; l > 0; --l) {
- XawTextSourceRead(src, l - 1, &tb, 1);
- c = tb.ptr[0];
- if (! isalnum(c) && c != '_' && c != '$')
- break;
- }
-
- len = 128; /* XXX */
- while (len > 0) {
- int i;
- char pstack[64];
- int pcnt = 0;
-
- XawTextSourceRead(src, l, &tb, len);
- for (sp = tb.ptr, i = tb.length; --i >= 0; ) {
- switch (c = *sp++) {
- case '\n':
- case ';':
- return (cp);
- case '=':
- if (cp[-1] != '=')
- return (cp - 1);
- if (len == 128)
- return (cp);
- break;
- case ',':
- if (pcnt <= 0)
- return (cp);
- break;
- case '(':
- pstack[pcnt] = ')';
- if (++pcnt >= sizeof(pstack))
- return (cp);
- break;
- case '[':
- pstack[pcnt] = ']';
- if (++pcnt >= sizeof(pstack))
- return (cp);
- break;
- case ')':
- case ']':
- if (--pcnt < 0 || pstack[pcnt] != c)
- return (cp);
- break;
- }
- *cp++ = c;
- }
- len -= tb.length;
- }
- return (cp);
-}
-
-static int input_avail; /* XXX kluge: do_command sets this when command
- * data from button is avaialble to force top level
- * to break out of its loop. */
-/*
- * Handle a button by running the command COMMAND.
- */
-static void
-do_command(w, command, call_data)
- Widget w;
- register char *command;
- caddr_t call_data;
-{
- char cmd_line[256];
- char buf[256];
- register char *out = cmd_line;
- char *cp;
- register char c;
- extern char *finish_command_input();
-
- while (c = *command++) {
- if (c == '%') {
- switch (*command++) {
- case 's': /* current selection */
- out = append_selection(out);
- break;
- case 'S': /* 1st selected "word" at curor */
- out = append_selection_word(out);
- break;
- case 'e': /* echo cmd before executing */
- break;
- case 'E': /* 1st selected expression at curor */
- out = append_selection_expr(out);
- break;
-
- case 'l': /* current line number */
- (void) sprintf(buf, "%d", current_lineno());
- for (cp = buf; c = *cp++; *out++ = c)
- ;
- break;
- case 'L': /* line we're stopped at */
- (void) sprintf(buf, "%d", source_window_line);
- for (cp = buf; c = *cp++; *out++ = c)
- ;
- break;
- case 'f': /* current file name */
- for (cp = source_window_symtab->filename;
- c = *cp++; *out++ = c)
- ;
- break;
- case 'b': /* break # we're stopped at */
- if (stop_breakpoint <= 0)
- /* if no breakpoint, don't do cmd */
- return;
-
- (void) sprintf(buf, "%d", stop_breakpoint);
- for (cp = buf; c = *cp++; *out++ = c)
- ;
- break;
- }
- } else
- *out++ = c;
- }
- *out = 0;
- reinitialize_more_filter();
- /* have to exit via readline or tty modes stay messed up */
- for (cp = cmd_line; c = *cp++; )
- rl_stuff_char(c);
- rl_stuff_char('\n');
- input_avail = 1;
-}
-
-/*
- * Define and display all the buttons.
- */
-static void
-addbutton(parent, name, function, closure)
- Widget parent;
- char *name;
- void (*function) ();
- caddr_t closure;
-{
- static XtCallbackRec Callback[] = {
- {NULL, (caddr_t) NULL},
- {NULL, (caddr_t) NULL},
- };
- static Arg commandArgs[] = {
- {XtNlabel, (XtArgVal) NULL},
- {XtNcallback, (XtArgVal) Callback},
- };
- Widget w;
- char wname[128];
- register char *cp;
-
- strcpy(wname, name);
- while ((cp = index(wname, '*')) || (cp = index(wname, '.')))
- *cp -= 0x10;
-
- if (w = XtNameToWidget(parent, wname))
- XtDestroyWidget(w);
-
- Callback[0].callback = (XtCallbackProc) function;
- Callback[0].closure = (caddr_t) closure;
- commandArgs[0].value = (XtArgVal) name;
- XtCreateManagedWidget(wname, commandWidgetClass, parent,
- commandArgs, XtNumber(commandArgs));
-}
-
-/*
- * Create the button windows and store them in `buttons'.
- */
-static void
-create_buttons(parent)
- Widget parent;
-{
- addbutton(parent, "quit", do_command, "quit");
-}
-
-static void
-button_command(arg)
- char *arg;
-{
- char *label;
- unsigned int len;
-
- if (! arg)
- error_no_arg("button label and command");
-
- for (len = strlen(arg); len > 0 && isspace(arg[len - 1]); --len)
- ;
- if (len == 0)
- error_no_arg("button label and command");
- arg[len] = 0;
-
- /* make a copy of button label & command for toolkit to use */
- label = malloc(len + 1);
- strcpy(label, arg);
-
- /* find the end of the label */
- if (*label == '"') {
- if ((arg = index(++label, '"')) == 0) {
- printf("button label missing closing quote\n");
- return;
- }
- *arg++ = 0;
- } else if (arg = index(label, ' '))
- *arg++ = 0;
- else
- arg = label;
-
- while (*arg && isspace(*arg))
- ++arg;
-
- addbutton(button_box_widget, label, do_command, arg);
-}
-
-static void
-button_delete_command(arg)
- char *arg;
-{
- unsigned int len;
- Widget w;
- register char *cp;
-
- if (! arg)
- error_no_arg("button name");
-
- for (len = strlen(arg); len > 0 && isspace(arg[len - 1]); --len)
- ;
- if (len == 0)
- error_no_arg("button name");
- arg[len] = 0;
-
- /* find the end of the label */
- if (*arg == '"') {
- if ((cp = index(++arg, '"')) == 0) {
- printf("button label missing closing quote\n");
- return;
- }
- *cp++ = 0;
- }
- while ((cp = index(arg, '*')) || (cp = index(arg, '.')))
- *cp -= 0x10;
-
- if (w = XtNameToWidget(button_box_widget, arg))
- XtDestroyWidget(w);
-}
-
-/*
- * Create a "label window" that just displays the string LABEL.
- */
-static Widget
-create_label(name, label)
- char *name, *label;
-{
- Arg args[1];
- Widget w;
-
- XtSetArg(args[0], XtNlabel, label);
- w = XtCreateManagedWidget(name, labelWidgetClass, containing_widget,
- args, XtNumber(args));
- return (w);
-}
-
-/*
- * Create a subwindow of PARENT that displays and scrolls the contents of
- * file FILENAME.
- */
-static Widget
-create_text_widget(parent, filename)
- Widget parent;
- char *filename;
-{
- static Arg arg[] = {
- {XtNstring, NULL},
- {XtNtype, XawAsciiFile},
- {XtNcursor, None},
- };
- Widget text_widget;
-
- arg[0].value = (XtArgVal)filename;
- text_widget = XtCreateManagedWidget("src", asciiTextWidgetClass,
- parent, arg, XtNumber(arg));
- return (text_widget);
-}
-
-/*
- * Entry point to create the widgets representing our display.
- */
-void
-xgdb_create_window()
-{
- /* initialize toolkit, setup defaults */
-#ifdef notyet
- main_widget = XtAppInitialize(&app_context, "Xgdb", NULL, 0,
- argcptr, argv, NULL, NULL, 0);
-#else
- char *dummy_argv[] = { "xgdb", 0 };
- int dummy_argc = 1;
- main_widget = XtAppInitialize(&app_context, "Xgdb", NULL, 0,
- &dummy_argc, dummy_argv, NULL, NULL, 0);
-#endif
- display = XtDisplay(main_widget);
- containing_widget = XtCreateManagedWidget("frame", panedWidgetClass,
- main_widget, NULL, 0);
-
- sprintf(version_label, "XGDB %s", version);
- button_box_widget = XtCreateManagedWidget("buttons", boxWidgetClass,
- containing_widget, NULL, 0);
- create_buttons(button_box_widget);
- source_name_widget = create_label("srcLabel", "No source file yet.");
- source_text_widget = create_text_widget(containing_widget, "/dev/null");
-
- XtRealizeWidget(main_widget);
- XFlush(display);
-}
-
-/*
- * If we use an X window, the readline input loop is told to call
- * this function before reading a character from stdin.
- */
-/*ARGSUSED*/
-static void
-xgdb_window_hook()
-{
- register int inmask = 1 << fileno(stdin);
- register int xmask = 1 << ConnectionNumber(display);
- register int nfds, pend;
- int input_rfds;
- XEvent ev;
-
- /*
- * Display our current idea of the `interesting' source file then
- * loop, dispatching window events until data is available on
- * stdin. Then return so the input data can be processed.
- */
- input_avail = 0;
- xgdb_display_source();
-
- input_rfds = 0;
- while (input_avail == 0 && (input_rfds & inmask) == 0) {
- pend = XPending(display);
- if (!pend) {
- input_rfds = inmask | xmask;
- nfds = select(32, &input_rfds, 0, 0,
- (struct timeval *)0);
- if (nfds == -1 && errno == EINTR)
- continue;
- }
- if (pend || (input_rfds & xmask)) {
- XNextEvent(display, &ev);
- XtDispatchEvent(&ev);
- }
- }
-}
-
-void
-_initialize_xgdb()
-{
- extern void (*window_hook) ();
- extern int inhibit_windows;
- extern struct cmd_list_element *deletelist;
-
- if (inhibit_windows)
- return;
-
- if (! displayname) {
- displayname = getenv("DISPLAY");
- if (! displayname) {
- fprintf(stderr, "xgdb: no display name\n");
- inhibit_windows = 1;
- return;
- }
- }
- xgdb_create_window();
- window_hook = xgdb_window_hook;
- add_com("button", class_support, button_command,
-"Add command button to xgdb window. First argument is button\n\
-label, second is command associated with button. Command can\n\
-include printf-like escapes:\n\
- %s for current selection,\n\
- %S for first 'word' of current selection,\n\
- %e for current selection or expression at insertion pt,\n\
- %E for current selection or expression at insertion pt,\n\
- %l for current line number,\n\
- %L for line program stopped at,\n\
- %f for current file name,\n\
- %b for current breakpoint number.");
- add_cmd("button", class_support, button_delete_command,
-"Delete a button from the xgdb window.\n\
-Argument is name of button to be deleted.",
- &deletelist);
-}